<commit_before>#include "ff_source_syntax.h"

#include <sstream>
#include <stack>

#include "sentence_metadata.h"
#include "array2d.h"
#include "filelib.h"

using namespace std;

// implements the source side syntax features described in Blunsom et al. (EMNLP 2008)
// source trees must be represented in Penn Treebank format, e.g.
//     (S (NP John) (VP (V left)))

// log transform to make long spans cluster together
// but preserve differences
inline int SpanSizeTransform(unsigned span_size) {
  if (!span_size) return 0;
  return static_cast<int>(log(span_size+1) / log(1.39)) - 1;
}

struct SourceSyntaxFeaturesImpl {
  SourceSyntaxFeaturesImpl() {}

  void InitializeGrids(const string& tree, unsigned src_len) {
    assert(tree.size() > 0);
    //fids_cat.clear();
    fids_ef.clear();
    src_tree.clear();
    //fids_cat.resize(src_len, src_len + 1);
    fids_ef.resize(src_len, src_len + 1);
    src_tree.resize(src_len, src_len + 1, TD::Convert("XX"));
    ParseTreeString(tree, src_len);
  }

  void ParseTreeString(const string& tree, unsigned src_len) {
    stack<pair<int, WordID> > stk;  // first = i, second = category
    pair<int, WordID> cur_cat; cur_cat.first = -1;
    unsigned i = 0;
    unsigned p = 0;
    while(p < tree.size()) {
      const char cur = tree[p];
      if (cur == '(') {
        stk.push(cur_cat);
        ++p;
        unsigned k = p + 1;
        while (k < tree.size() && tree[k] != ' ') { ++k; }
        cur_cat.first = i;
        cur_cat.second = TD::Convert(tree.substr(p, k - p));
        // cerr << "NT: '" << tree.substr(p, k-p) << "' (i=" << i << ")\n";
        p = k + 1;
      } else if (cur == ')') {
        unsigned k = p;
        while (k < tree.size() && tree[k] == ')') { ++k; }
        const unsigned num_closes = k - p;
        for (unsigned ci = 0; ci < num_closes; ++ci) {
          // cur_cat.second spans from cur_cat.first to i
          // cerr << TD::Convert(cur_cat.second) << " from " << cur_cat.first << " to " << i << endl;
          // NOTE: unary rule chains end up being labeled with the top-most category
          src_tree(cur_cat.first, i) = cur_cat.second;
          cur_cat = stk.top();
          stk.pop();
        }
        p = k;
        while (p < tree.size() && (tree[p] == ' ' || tree[p] == '\t')) { ++p; }
      } else if (cur == ' ' || cur == '\t') {
        cerr << "Unexpected whitespace in: " << tree << endl;
        abort();
      } else { // terminal symbol
        unsigned k = p + 1;
        do {
          while (k < tree.size() && tree[k] != ')' && tree[k] != ' ') { ++k; }
          // cerr << "TERM: '" << tree.substr(p, k-p) << "' (i=" << i << ")\n";
          ++i;
          assert(i <= src_len);
          while (k < tree.size() && tree[k] == ' ') { ++k; }
          p = k;
        } while (p < tree.size() && tree[p] != ')');
      }
    }
    // cerr << "i=" << i << "  src_len=" << src_len << endl;
    assert(i == src_len);  // make sure tree specified in src_tree is
                           // the same length as the source sentence
  }

  WordID FireFeatures(const TRule& rule, const int i, const int j, const WordID* ants, SparseVector<double>* feats) {
    //cerr << "fire features: " << rule.AsString() << " for " << i << "," << j << endl;
    const WordID lhs = src_tree(i,j);
    //int& fid_cat = fids_cat(i,j);
    int& fid_ef = fids_ef(i,j)[&rule];
    if (fid_ef <= 0) {
      ostringstream os;
      //ostringstream os2;
      os << "SYN:" << TD::Convert(lhs);
      //os2 << "SYN:" << TD::Convert(lhs) << '_' << SpanSizeTransform(j - i);
      //fid_cat = FD::Convert(os2.str());
      os << ':';
      unsigned ntc = 0;
      for (unsigned k = 0; k < rule.f_.size(); ++k) {
        if (k > 0) os << '_';
        int fj = rule.f_[k];
        if (fj <= 0) {
          os << '[' << TD::Convert(ants[ntc++]) << ']';
        } else {
          os << TD::Convert(fj);
        }
      }
      os << ':';
      for (unsigned k = 0; k < rule.e_.size(); ++k) {
        const int ei = rule.e_[k];
        if (k > 0) os << '_';
        if (ei <= 0)
          os << '[' << (1-ei) << ']';
        else
          os << TD::Convert(ei);
      }
      fid_ef = FD::Convert(os.str());
    }
    //if (fid_cat > 0)
    //  feats->set_value(fid_cat, 1.0);
    if (fid_ef > 0)
      feats->set_value(fid_ef, 1.0);
    return lhs;
  }

  Array2D<WordID> src_tree;  // src_tree(i,j) NT = type
  // mutable Array2D<int> fids_cat;   // this tends to overfit baddly
  mutable Array2D<map<const TRule*, int> > fids_ef;    // fires for fully lexicalized
};

SourceSyntaxFeatures::SourceSyntaxFeatures(const string& param) :
    FeatureFunction(sizeof(WordID)) {
  impl = new SourceSyntaxFeaturesImpl;
}

SourceSyntaxFeatures::~SourceSyntaxFeatures() {
  delete impl;
  impl = NULL;
}

void SourceSyntaxFeatures::TraversalFeaturesImpl(const SentenceMetadata& smeta,
                                     const Hypergraph::Edge& edge,
                                     const vector<const void*>& ant_contexts,
                                     SparseVector<double>* features,
                                     SparseVector<double>* estimated_features,
                                     void* context) const {
  WordID ants[8];
  for (unsigned i = 0; i < ant_contexts.size(); ++i)
    ants[i] = *static_cast<const WordID*>(ant_contexts[i]);

  *static_cast<WordID*>(context) =
     impl->FireFeatures(*edge.rule_, edge.i_, edge.j_, ants, features);
}

void SourceSyntaxFeatures::PrepareForInput(const SentenceMetadata& smeta) {
  impl->InitializeGrids(smeta.GetSGMLValue("src_tree"), smeta.GetSourceLength());
}

struct SourceSpanSizeFeaturesImpl {
  SourceSpanSizeFeaturesImpl() {}

  void InitializeGrids(unsigned src_len) {
    fids.clear();
    fids.resize(src_len, src_len + 1);
  }

  int FireFeatures(const TRule& rule, const int i, const int j, const WordID* ants, SparseVector<double>* feats) {
    if (rule.Arity() > 0) {
      int& fid = fids(i,j)[&rule];
      if (fid <= 0) {
        ostringstream os;
        os << "SSS:";
        unsigned ntc = 0;
        for (unsigned k = 0; k < rule.f_.size(); ++k) {
          if (k > 0) os << '_';
          int fj = rule.f_[k];
          if (fj <= 0) {
            os << '[' << TD::Convert(-fj) << ants[ntc++] << ']';
          } else {
            os << TD::Convert(fj);
          }
        }
        fid = FD::Convert(os.str());
      }
      if (fid > 0)
        feats->set_value(fid, 1.0);
    }
    return SpanSizeTransform(j - i);
  }

  mutable Array2D<map<const TRule*, int> > fids;
};

SourceSpanSizeFeatures::SourceSpanSizeFeatures(const string& param) :
    FeatureFunction(sizeof(char)) {
  impl = new SourceSpanSizeFeaturesImpl;
}

SourceSpanSizeFeatures::~SourceSpanSizeFeatures() {
  delete impl;
  impl = NULL;
}

void SourceSpanSizeFeatures::TraversalFeaturesImpl(const SentenceMetadata& smeta,
                                     const Hypergraph::Edge& edge,
                                     const vector<const void*>& ant_contexts,
                                     SparseVector<double>* features,
                                     SparseVector<double>* estimated_features,
                                     void* context) const {
  int ants[8];
  for (unsigned i = 0; i < ant_contexts.size(); ++i)
    ants[i] = *static_cast<const char*>(ant_contexts[i]);

  *static_cast<char*>(context) =
     impl->FireFeatures(*edge.rule_, edge.i_, edge.j_, ants, features);
}

void SourceSpanSizeFeatures::PrepareForInput(const SentenceMetadata& smeta) {
  impl->InitializeGrids(smeta.GetSourceLength());
}

<commit_msg>add target side for sss features<commit_after>#include "ff_source_syntax.h"

#include <sstream>
#include <stack>

#include "sentence_metadata.h"
#include "array2d.h"
#include "filelib.h"

using namespace std;

// implements the source side syntax features described in Blunsom et al. (EMNLP 2008)
// source trees must be represented in Penn Treebank format, e.g.
//     (S (NP John) (VP (V left)))

// log transform to make long spans cluster together
// but preserve differences
inline int SpanSizeTransform(unsigned span_size) {
  if (!span_size) return 0;
  return static_cast<int>(log(span_size+1) / log(1.39)) - 1;
}

struct SourceSyntaxFeaturesImpl {
  SourceSyntaxFeaturesImpl() {}

  void InitializeGrids(const string& tree, unsigned src_len) {
    assert(tree.size() > 0);
    //fids_cat.clear();
    fids_ef.clear();
    src_tree.clear();
    //fids_cat.resize(src_len, src_len + 1);
    fids_ef.resize(src_len, src_len + 1);
    src_tree.resize(src_len, src_len + 1, TD::Convert("XX"));
    ParseTreeString(tree, src_len);
  }

  void ParseTreeString(const string& tree, unsigned src_len) {
    stack<pair<int, WordID> > stk;  // first = i, second = category
    pair<int, WordID> cur_cat; cur_cat.first = -1;
    unsigned i = 0;
    unsigned p = 0;
    while(p < tree.size()) {
      const char cur = tree[p];
      if (cur == '(') {
        stk.push(cur_cat);
        ++p;
        unsigned k = p + 1;
        while (k < tree.size() && tree[k] != ' ') { ++k; }
        cur_cat.first = i;
        cur_cat.second = TD::Convert(tree.substr(p, k - p));
        // cerr << "NT: '" << tree.substr(p, k-p) << "' (i=" << i << ")\n";
        p = k + 1;
      } else if (cur == ')') {
        unsigned k = p;
        while (k < tree.size() && tree[k] == ')') { ++k; }
        const unsigned num_closes = k - p;
        for (unsigned ci = 0; ci < num_closes; ++ci) {
          // cur_cat.second spans from cur_cat.first to i
          // cerr << TD::Convert(cur_cat.second) << " from " << cur_cat.first << " to " << i << endl;
          // NOTE: unary rule chains end up being labeled with the top-most category
          src_tree(cur_cat.first, i) = cur_cat.second;
          cur_cat = stk.top();
          stk.pop();
        }
        p = k;
        while (p < tree.size() && (tree[p] == ' ' || tree[p] == '\t')) { ++p; }
      } else if (cur == ' ' || cur == '\t') {
        cerr << "Unexpected whitespace in: " << tree << endl;
        abort();
      } else { // terminal symbol
        unsigned k = p + 1;
        do {
          while (k < tree.size() && tree[k] != ')' && tree[k] != ' ') { ++k; }
          // cerr << "TERM: '" << tree.substr(p, k-p) << "' (i=" << i << ")\n";
          ++i;
          assert(i <= src_len);
          while (k < tree.size() && tree[k] == ' ') { ++k; }
          p = k;
        } while (p < tree.size() && tree[p] != ')');
      }
    }
    // cerr << "i=" << i << "  src_len=" << src_len << endl;
    assert(i == src_len);  // make sure tree specified in src_tree is
                           // the same length as the source sentence
  }

  WordID FireFeatures(const TRule& rule, const int i, const int j, const WordID* ants, SparseVector<double>* feats) {
    //cerr << "fire features: " << rule.AsString() << " for " << i << "," << j << endl;
    const WordID lhs = src_tree(i,j);
    //int& fid_cat = fids_cat(i,j);
    int& fid_ef = fids_ef(i,j)[&rule];
    if (fid_ef <= 0) {
      ostringstream os;
      //ostringstream os2;
      os << "SYN:" << TD::Convert(lhs);
      //os2 << "SYN:" << TD::Convert(lhs) << '_' << SpanSizeTransform(j - i);
      //fid_cat = FD::Convert(os2.str());
      os << ':';
      unsigned ntc = 0;
      for (unsigned k = 0; k < rule.f_.size(); ++k) {
        if (k > 0) os << '_';
        int fj = rule.f_[k];
        if (fj <= 0) {
          os << '[' << TD::Convert(ants[ntc++]) << ']';
        } else {
          os << TD::Convert(fj);
        }
      }
      os << ':';
      for (unsigned k = 0; k < rule.e_.size(); ++k) {
        const int ei = rule.e_[k];
        if (k > 0) os << '_';
        if (ei <= 0)
          os << '[' << (1-ei) << ']';
        else
          os << TD::Convert(ei);
      }
      fid_ef = FD::Convert(os.str());
    }
    //if (fid_cat > 0)
    //  feats->set_value(fid_cat, 1.0);
    if (fid_ef > 0)
      feats->set_value(fid_ef, 1.0);
    return lhs;
  }

  Array2D<WordID> src_tree;  // src_tree(i,j) NT = type
  // mutable Array2D<int> fids_cat;   // this tends to overfit baddly
  mutable Array2D<map<const TRule*, int> > fids_ef;    // fires for fully lexicalized
};

SourceSyntaxFeatures::SourceSyntaxFeatures(const string& param) :
    FeatureFunction(sizeof(WordID)) {
  impl = new SourceSyntaxFeaturesImpl;
}

SourceSyntaxFeatures::~SourceSyntaxFeatures() {
  delete impl;
  impl = NULL;
}

void SourceSyntaxFeatures::TraversalFeaturesImpl(const SentenceMetadata& smeta,
                                     const Hypergraph::Edge& edge,
                                     const vector<const void*>& ant_contexts,
                                     SparseVector<double>* features,
                                     SparseVector<double>* estimated_features,
                                     void* context) const {
  WordID ants[8];
  for (unsigned i = 0; i < ant_contexts.size(); ++i)
    ants[i] = *static_cast<const WordID*>(ant_contexts[i]);

  *static_cast<WordID*>(context) =
     impl->FireFeatures(*edge.rule_, edge.i_, edge.j_, ants, features);
}

void SourceSyntaxFeatures::PrepareForInput(const SentenceMetadata& smeta) {
  impl->InitializeGrids(smeta.GetSGMLValue("src_tree"), smeta.GetSourceLength());
}

struct SourceSpanSizeFeaturesImpl {
  SourceSpanSizeFeaturesImpl() {}

  void InitializeGrids(unsigned src_len) {
    fids.clear();
    fids.resize(src_len, src_len + 1);
  }

  int FireFeatures(const TRule& rule, const int i, const int j, const WordID* ants, SparseVector<double>* feats) {
    if (rule.Arity() > 0) {
      int& fid = fids(i,j)[&rule];
      if (fid <= 0) {
        ostringstream os;
        os << "SSS:";
        unsigned ntc = 0;
        for (unsigned k = 0; k < rule.f_.size(); ++k) {
          if (k > 0) os << '_';
          int fj = rule.f_[k];
          if (fj <= 0) {
            os << '[' << TD::Convert(-fj) << ants[ntc++] << ']';
          } else {
            os << TD::Convert(fj);
          }
        }
        os << ':';
        for (unsigned k = 0; k < rule.e_.size(); ++k) {
          const int ei = rule.e_[k];
          if (k > 0) os << '_';
          if (ei <= 0)
            os << '[' << (1-ei) << ']';
          else
            os << TD::Convert(ei);
        }
        fid = FD::Convert(os.str());
      }
      if (fid > 0)
        feats->set_value(fid, 1.0);
    }
    return SpanSizeTransform(j - i);
  }

  mutable Array2D<map<const TRule*, int> > fids;
};

SourceSpanSizeFeatures::SourceSpanSizeFeatures(const string& param) :
    FeatureFunction(sizeof(char)) {
  impl = new SourceSpanSizeFeaturesImpl;
}

SourceSpanSizeFeatures::~SourceSpanSizeFeatures() {
  delete impl;
  impl = NULL;
}

void SourceSpanSizeFeatures::TraversalFeaturesImpl(const SentenceMetadata& smeta,
                                     const Hypergraph::Edge& edge,
                                     const vector<const void*>& ant_contexts,
                                     SparseVector<double>* features,
                                     SparseVector<double>* estimated_features,
                                     void* context) const {
  int ants[8];
  for (unsigned i = 0; i < ant_contexts.size(); ++i)
    ants[i] = *static_cast<const char*>(ant_contexts[i]);

  *static_cast<char*>(context) =
     impl->FireFeatures(*edge.rule_, edge.i_, edge.j_, ants, features);
}

void SourceSpanSizeFeatures::PrepareForInput(const SentenceMetadata& smeta) {
  impl->InitializeGrids(smeta.GetSourceLength());
}

<|endoftext|>


<commit_before>#include "message.hpp"
#include "server.hpp"
#include "Cereal.hpp"
#include <vector>
#include <iostream>

using namespace std;

MqttFixedHeader::MqttFixedHeader():
    type(), dup(), qos(), retain(), remaining() {
}

MqttFixedHeader::MqttFixedHeader(MqttType t, bool d, ubyte q, bool rt, uint re):
    type(t), dup(d), qos(q), retain(rt), remaining(re) {
}

void MqttFixedHeader::cerealise(Cereal& cereal) {
    cereal.grainBits(type, 4);
    cereal.grainBits(dup, 1);
    cereal.grainBits(qos, 2);
    cereal.grainBits(retain, 1);

    switch(cereal.getType()) {
    case Cereal::Type::Write:
        setRemainingSize(cereal);
        break;

    case Cereal::Type::Read:
        remaining = getRemainingSize(cereal);
        break;
    }
}

uint MqttFixedHeader::getRemainingSize(Cereal& cereal) {
    //algorithm straight from the MQTT spec
    int multiplier = 1;
    uint value = 0;
    ubyte digit;
    do {
        cereal.grain(digit);
        value += (digit & 127) * multiplier;
        multiplier *= 128;
    } while((digit & 128) != 0);

    return value;
}

void MqttFixedHeader::setRemainingSize(Cereal& cereal) const {
    //algorithm straight from the MQTT spec
    vector<ubyte> digits;
    uint x = remaining;
    do {
        ubyte digit = x % 128;
        x /= 128;
        if(x > 0) {
            digit = digit | 0x80;
        }
        digits.push_back(digit);
    } while(x > 0);

    for(auto b: digits) cereal.grain(b);
}

class MqttConnect: public MqttMessage {
 public:

    MqttConnect(MqttFixedHeader h):header(h) { }

    void cerealise(Cereal& cereal) {
        cereal.grain(header);
        cereal.grain(protoName);
        cereal.grain(protoVersion);

        cereal.grainBits(hasUserName, 1);
        cereal.grainBits(hasPassword, 1);
        cereal.grainBits(hasWillRetain, 1);
        cereal.grainBits(willQos, 2);
        cereal.grainBits(hasWill, 1);
        cereal.grainBits(hasClear, 1);
        cereal.grainBits(reserved, 1);

        cereal.grain(keepAlive);
        cereal.grain(clientId);

        if(hasWill) cereal.grain(willTopic);
        if(hasWill) cereal.grain(willMessage);
        if(hasUserName) cereal.grain(userName);
        if(hasPassword) cereal.grain(password);
    }

    bool isBadClientId() const { return clientId.length() < 1 || clientId.length() > 23; }

    MqttFixedHeader header;
    string protoName;
    ubyte protoVersion;
    bool hasUserName; //1
    bool hasPassword; //1
    bool hasWillRetain; //1
    ubyte willQos; //2
    bool hasWill; //1
    bool hasClear; //1
    bool reserved; //1
    ushort keepAlive;
    string clientId;
    string willTopic;
    string willMessage;
    string userName;
    string password;
};

class MqttConnack: public MqttMessage {
public:
    enum class Code {
        ACCEPTED = 0,
        BAD_VERSION = 1,
        BAD_ID = 2,
        SERVER_UNAVAILABLE = 3,
        BAD_USER_OR_PWD = 4,
        NO_AUTH = 5,
    };

    MqttConnack():
        header(MqttType::CONNACK, false, 0, false, 2) {
    }

    MqttConnack(Code c):
        MqttConnack() {
        code = c;
    }

    void cerealise(Cereal& cereal) {
        cereal.grain(header);
        cereal.grain(reserved);
        cereal.grainBits(code, 8);
    }

    MqttFixedHeader header;
    ubyte reserved;
    Code code;
};

class MqttPublish: public MqttMessage {
public:
    MqttPublish(MqttFixedHeader h):header(h) {

    }

    MqttPublish(string topic, std::vector<ubyte> payload, ushort msgId = 0):
        MqttPublish(false, 0, false, topic, payload, msgId) {
    }

    MqttPublish(bool dup, ubyte qos, bool retain, string t, std::vector<ubyte> p, ushort mid = 0) {
        const auto topicLen = t.length() + 2; //2 for length
        auto remaining = qos ? topicLen + 2 /*msgId*/ : topicLen;
        remaining += p.size();

        header = MqttFixedHeader(MqttType::PUBLISH, dup, qos, retain, remaining);
        topic = t;
        payload = std::move(p);
        msgId = mid;
    }

    void cerealise(Cereal& cereal) {
        cereal.grain(header);
        cereal.grain(topic);

        auto payloadLen = header.remaining - (topic.length() + MqttFixedHeader::SIZE);
        if(header.qos) {
            if(header.remaining < 7 && cereal.getType() == Cereal::Type::Read) {
                cerr << "Error: PUBLISH message with QOS but no message ID" << endl;
            } else {
                cereal.grain(msgId);
                payloadLen -= 2;
            }
        }
        if(cereal.getType() == Cereal::Type::Read) payload.resize(payloadLen);
        for(auto& b: payload) cereal.grain(b);
    }

    void handle(MqttServer& server, MqttConnection& connection) const override {
        (void)connection;
        server.publish(topic, payload);
    }

    MqttFixedHeader header;
    string topic;
    std::vector<ubyte> payload;
    ushort msgId;
};

MqttSubscribe::MqttSubscribe(MqttFixedHeader h):header(h) {

}

void MqttSubscribe::handle(MqttServer& server, MqttConnection& connection) const {
    server.subscribe(connection, msgId, topics);
}

void MqttSubscribe::Topic::cerealise(Cereal& cereal) {
    cereal.grain(topic);
    cereal.grain(qos);
}

void MqttSubscribe::cerealise(Cereal& cereal) {
    cereal.grain(header);
    cereal.grain(msgId);
    ushort size;
    cereal.grain(size);
    if(topics.size() != size) topics.resize(size);
    for(auto& t: topics) cereal.grain(t);
}

// class MqttSuback: MqttMessage {
// public:

//     this(MqttFixedHeader header) {
//         this.header = header;
//     }

//     this(in ushort msgId, in std::vector<ubyte> qos) {
//         this.header = MqttFixedHeader(MqttType.SUBACK, false, 0, false, cast(uint)qos.length + 2);
//         this.msgId = msgId;
//         this.qos = qos.dup;
//     }

//     MqttFixedHeader header;
//     ushort msgId;
//     @RawArray std::vector<ubyte> qos;
// }

// class MqttUnsubscribe: MqttMessage {
//     this(MqttFixedHeader header) {
//         this.header = header;
//     }

//     override void handle(MqttServer server, MqttConnection connection) const {
//         server.unsubscribe(connection, msgId, topics);
//     }

//     MqttFixedHeader header;
//     ushort msgId;
//     @RawArray string[] topics;
// }

// class MqttUnsuback: MqttMessage {
//     this(in ushort msgId) {
//         this.header = MqttFixedHeader(MqttType.UNSUBACK, false, 0, false, 2);
//         this.msgId = msgId;
//     }

//     this(MqttFixedHeader header) {
//         this.header = header;
//     }

//     MqttFixedHeader header;
//     ushort msgId;
// }

// class MqttDisconnect: MqttMessage {
//     override void handle(MqttServer server, MqttConnection connection) const {
//         server.unsubscribe(connection);
//         connection.disconnect();
//     }
// }

// class MqttPingReq: MqttMessage {
//     override void handle(MqttServer server, MqttConnection connection) const {
//         server.ping(connection);
//     }
// }

// class MqttPingResp: MqttMessage {
//     const(std::vector<ubyte>) encode() const {
//         return [0xd0, 0x00];
//     }
// }
<commit_msg>Uncommented MqttSuback<commit_after>#include "message.hpp"
#include "server.hpp"
#include "Cereal.hpp"
#include <vector>
#include <iostream>

using namespace std;

MqttFixedHeader::MqttFixedHeader():
    type(), dup(), qos(), retain(), remaining() {
}

MqttFixedHeader::MqttFixedHeader(MqttType t, bool d, ubyte q, bool rt, uint re):
    type(t), dup(d), qos(q), retain(rt), remaining(re) {
}

void MqttFixedHeader::cerealise(Cereal& cereal) {
    cereal.grainBits(type, 4);
    cereal.grainBits(dup, 1);
    cereal.grainBits(qos, 2);
    cereal.grainBits(retain, 1);

    switch(cereal.getType()) {
    case Cereal::Type::Write:
        setRemainingSize(cereal);
        break;

    case Cereal::Type::Read:
        remaining = getRemainingSize(cereal);
        break;
    }
}

uint MqttFixedHeader::getRemainingSize(Cereal& cereal) {
    //algorithm straight from the MQTT spec
    int multiplier = 1;
    uint value = 0;
    ubyte digit;
    do {
        cereal.grain(digit);
        value += (digit & 127) * multiplier;
        multiplier *= 128;
    } while((digit & 128) != 0);

    return value;
}

void MqttFixedHeader::setRemainingSize(Cereal& cereal) const {
    //algorithm straight from the MQTT spec
    vector<ubyte> digits;
    uint x = remaining;
    do {
        ubyte digit = x % 128;
        x /= 128;
        if(x > 0) {
            digit = digit | 0x80;
        }
        digits.push_back(digit);
    } while(x > 0);

    for(auto b: digits) cereal.grain(b);
}

class MqttConnect: public MqttMessage {
 public:

    MqttConnect(MqttFixedHeader h):header(h) { }

    void cerealise(Cereal& cereal) {
        cereal.grain(header);
        cereal.grain(protoName);
        cereal.grain(protoVersion);

        cereal.grainBits(hasUserName, 1);
        cereal.grainBits(hasPassword, 1);
        cereal.grainBits(hasWillRetain, 1);
        cereal.grainBits(willQos, 2);
        cereal.grainBits(hasWill, 1);
        cereal.grainBits(hasClear, 1);
        cereal.grainBits(reserved, 1);

        cereal.grain(keepAlive);
        cereal.grain(clientId);

        if(hasWill) cereal.grain(willTopic);
        if(hasWill) cereal.grain(willMessage);
        if(hasUserName) cereal.grain(userName);
        if(hasPassword) cereal.grain(password);
    }

    bool isBadClientId() const { return clientId.length() < 1 || clientId.length() > 23; }

    MqttFixedHeader header;
    string protoName;
    ubyte protoVersion;
    bool hasUserName; //1
    bool hasPassword; //1
    bool hasWillRetain; //1
    ubyte willQos; //2
    bool hasWill; //1
    bool hasClear; //1
    bool reserved; //1
    ushort keepAlive;
    string clientId;
    string willTopic;
    string willMessage;
    string userName;
    string password;
};

class MqttConnack: public MqttMessage {
public:
    enum class Code {
        ACCEPTED = 0,
        BAD_VERSION = 1,
        BAD_ID = 2,
        SERVER_UNAVAILABLE = 3,
        BAD_USER_OR_PWD = 4,
        NO_AUTH = 5,
    };

    MqttConnack():
        header(MqttType::CONNACK, false, 0, false, 2) {
    }

    MqttConnack(Code c):
        MqttConnack() {
        code = c;
    }

    void cerealise(Cereal& cereal) {
        cereal.grain(header);
        cereal.grain(reserved);
        cereal.grainBits(code, 8);
    }

    MqttFixedHeader header;
    ubyte reserved;
    Code code;
};

class MqttPublish: public MqttMessage {
public:
    MqttPublish(MqttFixedHeader h):header(h) {

    }

    MqttPublish(string topic, std::vector<ubyte> payload, ushort msgId = 0):
        MqttPublish(false, 0, false, topic, payload, msgId) {
    }

    MqttPublish(bool dup, ubyte qos, bool retain, string t, std::vector<ubyte> p, ushort mid = 0) {
        const auto topicLen = t.length() + 2; //2 for length
        auto remaining = qos ? topicLen + 2 /*msgId*/ : topicLen;
        remaining += p.size();

        header = MqttFixedHeader(MqttType::PUBLISH, dup, qos, retain, remaining);
        topic = t;
        payload = std::move(p);
        msgId = mid;
    }

    void cerealise(Cereal& cereal) {
        cereal.grain(header);
        cereal.grain(topic);

        auto payloadLen = header.remaining - (topic.length() + MqttFixedHeader::SIZE);
        if(header.qos) {
            if(header.remaining < 7 && cereal.getType() == Cereal::Type::Read) {
                cerr << "Error: PUBLISH message with QOS but no message ID" << endl;
            } else {
                cereal.grain(msgId);
                payloadLen -= 2;
            }
        }
        if(cereal.getType() == Cereal::Type::Read) payload.resize(payloadLen);
        for(auto& b: payload) cereal.grain(b);
    }

    void handle(MqttServer& server, MqttConnection& connection) const override {
        (void)connection;
        server.publish(topic, payload);
    }

    MqttFixedHeader header;
    string topic;
    std::vector<ubyte> payload;
    ushort msgId;
};

MqttSubscribe::MqttSubscribe(MqttFixedHeader h):header(h) {

}

void MqttSubscribe::handle(MqttServer& server, MqttConnection& connection) const {
    server.subscribe(connection, msgId, topics);
}

void MqttSubscribe::Topic::cerealise(Cereal& cereal) {
    cereal.grain(topic);
    cereal.grain(qos);
}

void MqttSubscribe::cerealise(Cereal& cereal) {
    cereal.grain(header);
    cereal.grain(msgId);
    ushort size;
    cereal.grain(size);
    if(topics.size() != size) topics.resize(size);
    for(auto& t: topics) cereal.grain(t);
}

class MqttSuback: MqttMessage {
public:

    MqttSuback(MqttFixedHeader h):header(h) {

    }

    MqttSuback(ushort m, std::vector<ubyte> q):
        header(MqttType::SUBACK, false, 0, false, qos.size() + 2),
        msgId(m),
        qos(std::move(q)) {
    }

    void cerealise(Cereal& cereal) {
        cereal.grain(header);
        cereal.grain(msgId);
        ushort size;
        cereal.grain(size);
        if(qos.size() != size) qos.resize(size);
        for(auto& q: qos) cereal.grain(q);
    }

    MqttFixedHeader header;
    ushort msgId;
    std::vector<ubyte> qos;
};

// class MqttUnsubscribe: MqttMessage {
//     this(MqttFixedHeader header) {
//         this.header = header;
//     }

//     override void handle(MqttServer server, MqttConnection connection) const {
//         server.unsubscribe(connection, msgId, topics);
//     }

//     MqttFixedHeader header;
//     ushort msgId;
//     @RawArray string[] topics;
// }

// class MqttUnsuback: MqttMessage {
//     this(in ushort msgId) {
//         this.header = MqttFixedHeader(MqttType.UNSUBACK, false, 0, false, 2);
//         this.msgId = msgId;
//     }

//     this(MqttFixedHeader header) {
//         this.header = header;
//     }

//     MqttFixedHeader header;
//     ushort msgId;
// }

// class MqttDisconnect: MqttMessage {
//     override void handle(MqttServer server, MqttConnection connection) const {
//         server.unsubscribe(connection);
//         connection.disconnect();
//     }
// }

// class MqttPingReq: MqttMessage {
//     override void handle(MqttServer server, MqttConnection connection) const {
//         server.ping(connection);
//     }
// }

// class MqttPingResp: MqttMessage {
//     const(std::vector<ubyte>) encode() const {
//         return [0xd0, 0x00];
//     }
// }
<|endoftext|>


<commit_before>#include "core/tz.hpp"
#include "core/window.hpp"
#include "core/profiling/zone.hpp"
#include "core/matrix_transform.hpp"
#include "core/time.hpp"
#include "gl/device.hpp"
#include "gl/renderer.hpp"
#include "gl/resource.hpp"
#include "gl/imported_shaders.hpp"

#include ImportedShaderHeader(tz_terrain_demo, vertex)
#include ImportedShaderHeader(tz_terrain_demo, tesscon)
#include ImportedShaderHeader(tz_terrain_demo, tesseval)
#include ImportedShaderHeader(tz_terrain_demo, fragment)

int main()
{
	tz::initialise
	({
		.name = "tz_terrain_demo",
	});
	{
		struct BufferData
		{
			tz::Mat4 model = tz::model({0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f});
			tz::Mat4 view = tz::Mat4::identity();
			tz::Mat4 projection = tz::Mat4::identity();
		};

		tz::gl::Device dev;

		tz::gl::BufferResource buf = tz::gl::BufferResource::from_one(BufferData{}, tz::gl::ResourceAccess::DynamicFixed);

		tz::gl::RendererInfo rinfo;
		tz::gl::ResourceHandle bufh = rinfo.add_resource(buf);
		rinfo.shader().set_shader(tz::gl::ShaderStage::Vertex, ImportedShaderSource(tz_terrain_demo, vertex));
		rinfo.shader().set_shader(tz::gl::ShaderStage::TessellationControl, ImportedShaderSource(tz_terrain_demo, tesscon));
		rinfo.shader().set_shader(tz::gl::ShaderStage::TessellationEvaluation, ImportedShaderSource(tz_terrain_demo, tesseval));
		rinfo.shader().set_shader(tz::gl::ShaderStage::Fragment, ImportedShaderSource(tz_terrain_demo, fragment));
		rinfo.set_clear_colour({0.0f, 0.765f, 1.0f, 1.0f});

		tz::gl::Renderer renderer = dev.create_renderer(rinfo);
		tz::Vec3 camera_position{0.0f, 2.0f, 1.0f};
		tz::Vec3 cam_rot{0.0f, 0.0f, 0.0f};
		bool wireframe_mode = false;
		using namespace tz::literals;
		tz::Delay fixed_update{25_ms};

		constexpr float multiplier = 1.5f;
		while(!tz::window().is_close_requested())
		{
			TZ_FRAME_BEGIN;
			tz::window().update();
			renderer.render(2);
			TZ_FRAME_END;

			// Every 25ms, we do a fixed-update.
			if(fixed_update.done())
			{
				fixed_update.reset();

				// If Q is pressed, toggle wireframe mode via renderer edit.
				if(tz::window().get_keyboard_state().is_key_down(tz::KeyCode::Q))
				{
					renderer.edit
					({
						.render_state_edit = tz::gl::RendererStateEditRequest
						{
							.wireframe_mode = wireframe_mode
						}
					});
					wireframe_mode = !wireframe_mode;
				}
				// Retrieve the dynamic buffer resource data.
				BufferData& bufd = renderer.get_resource(bufh)->data_as<BufferData>().front();

				// Dragging the mouse influences the camera rotation.
				static tz::Vec2i mouse_position;
				auto mpi = static_cast<tz::Vec2i>(tz::window().get_mouse_position_state().get_mouse_position());
				if(tz::window().get_mouse_button_state().is_mouse_button_down(tz::MouseButton::Left))
				{
					// Get mouse delta since last frame.
					tz::Vec2i mouse_delta = mpi - mouse_position;
					constexpr float rot_multiplier = 0.003f;
					cam_rot[1] -= mouse_delta[0] * rot_multiplier;
					cam_rot[0] -= mouse_delta[1] * rot_multiplier;
				}
				mouse_position = mpi;

				bufd.view = tz::view(camera_position, cam_rot);
				// Recalculate projection every fixed update. This is a massive waste of time but easily guarantees no distortion if the window is ever resized.
				const float aspect_ratio = static_cast<float>(tz::window().get_width()) / tz::window().get_height();
				bufd.projection = tz::perspective(1.6f, aspect_ratio, 0.1f, 1000.0f);
				// WASD move the camera position around. Space and LeftShift move camera directly up or down.

				tz::Vec4 cam_forward4 = bufd.view * tz::Vec4{0.0f, 0.0f, -1.0f, 0.0f};
				tz::Vec4 cam_right4 = bufd.view * tz::Vec4{-1.0f, 0.0f, 0.0f, 0.0f};
				tz::Vec3 cam_forward = cam_forward4.swizzle<0, 1, 2>();
				tz::Vec3 cam_right = cam_right4.swizzle<0, 1, 2>();
				if(tz::window().get_keyboard_state().is_key_down(tz::KeyCode::W))
				{
					camera_position += cam_forward * multiplier;
				}
				if(tz::window().get_keyboard_state().is_key_down(tz::KeyCode::S))
				{
					camera_position -= cam_forward * multiplier;
				}
				if(tz::window().get_keyboard_state().is_key_down(tz::KeyCode::Space))
				{
					camera_position[1] += multiplier;
				}
				if(tz::window().get_keyboard_state().is_key_down(tz::KeyCode::LeftShift))
				{
					camera_position[1] -= multiplier;
				}
				if(tz::window().get_keyboard_state().is_key_down(tz::KeyCode::A))
				{
					camera_position += cam_right * multiplier;
				}
				if(tz::window().get_keyboard_state().is_key_down(tz::KeyCode::D))
				{
					camera_position -= cam_right * multiplier;
				}

			}
		}
	}
	tz::terminate();
}
<commit_msg>* tz_terrain_demo - Camera now spawns slightly above terrain as previously you could be clipping inside the terrain<commit_after>#include "core/tz.hpp"
#include "core/window.hpp"
#include "core/profiling/zone.hpp"
#include "core/matrix_transform.hpp"
#include "core/time.hpp"
#include "gl/device.hpp"
#include "gl/renderer.hpp"
#include "gl/resource.hpp"
#include "gl/imported_shaders.hpp"

#include ImportedShaderHeader(tz_terrain_demo, vertex)
#include ImportedShaderHeader(tz_terrain_demo, tesscon)
#include ImportedShaderHeader(tz_terrain_demo, tesseval)
#include ImportedShaderHeader(tz_terrain_demo, fragment)

int main()
{
	tz::initialise
	({
		.name = "tz_terrain_demo",
	});
	{
		struct BufferData
		{
			tz::Mat4 model = tz::model({0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f});
			tz::Mat4 view = tz::Mat4::identity();
			tz::Mat4 projection = tz::Mat4::identity();
		};

		tz::gl::Device dev;

		tz::gl::BufferResource buf = tz::gl::BufferResource::from_one(BufferData{}, tz::gl::ResourceAccess::DynamicFixed);

		tz::gl::RendererInfo rinfo;
		tz::gl::ResourceHandle bufh = rinfo.add_resource(buf);
		rinfo.shader().set_shader(tz::gl::ShaderStage::Vertex, ImportedShaderSource(tz_terrain_demo, vertex));
		rinfo.shader().set_shader(tz::gl::ShaderStage::TessellationControl, ImportedShaderSource(tz_terrain_demo, tesscon));
		rinfo.shader().set_shader(tz::gl::ShaderStage::TessellationEvaluation, ImportedShaderSource(tz_terrain_demo, tesseval));
		rinfo.shader().set_shader(tz::gl::ShaderStage::Fragment, ImportedShaderSource(tz_terrain_demo, fragment));
		rinfo.set_clear_colour({0.0f, 0.765f, 1.0f, 1.0f});

		tz::gl::Renderer renderer = dev.create_renderer(rinfo);
		tz::Vec3 camera_position{0.0f, 50.0f, 1.0f};
		tz::Vec3 cam_rot{0.0f, 0.0f, 0.0f};
		bool wireframe_mode = false;
		using namespace tz::literals;
		tz::Delay fixed_update{25_ms};

		constexpr float multiplier = 1.5f;
		while(!tz::window().is_close_requested())
		{
			TZ_FRAME_BEGIN;
			tz::window().update();
			renderer.render(2);
			TZ_FRAME_END;

			// Every 25ms, we do a fixed-update.
			if(fixed_update.done())
			{
				fixed_update.reset();

				// If Q is pressed, toggle wireframe mode via renderer edit.
				if(tz::window().get_keyboard_state().is_key_down(tz::KeyCode::Q))
				{
					renderer.edit
					({
						.render_state_edit = tz::gl::RendererStateEditRequest
						{
							.wireframe_mode = wireframe_mode
						}
					});
					wireframe_mode = !wireframe_mode;
				}
				// Retrieve the dynamic buffer resource data.
				BufferData& bufd = renderer.get_resource(bufh)->data_as<BufferData>().front();

				// Dragging the mouse influences the camera rotation.
				static tz::Vec2i mouse_position;
				auto mpi = static_cast<tz::Vec2i>(tz::window().get_mouse_position_state().get_mouse_position());
				if(tz::window().get_mouse_button_state().is_mouse_button_down(tz::MouseButton::Left))
				{
					// Get mouse delta since last frame.
					tz::Vec2i mouse_delta = mpi - mouse_position;
					constexpr float rot_multiplier = 0.003f;
					cam_rot[1] -= mouse_delta[0] * rot_multiplier;
					cam_rot[0] -= mouse_delta[1] * rot_multiplier;
				}
				mouse_position = mpi;

				bufd.view = tz::view(camera_position, cam_rot);
				// Recalculate projection every fixed update. This is a massive waste of time but easily guarantees no distortion if the window is ever resized.
				const float aspect_ratio = static_cast<float>(tz::window().get_width()) / tz::window().get_height();
				bufd.projection = tz::perspective(1.6f, aspect_ratio, 0.1f, 1000.0f);
				// WASD move the camera position around. Space and LeftShift move camera directly up or down.

				tz::Vec4 cam_forward4 = bufd.view * tz::Vec4{0.0f, 0.0f, -1.0f, 0.0f};
				tz::Vec4 cam_right4 = bufd.view * tz::Vec4{-1.0f, 0.0f, 0.0f, 0.0f};
				tz::Vec3 cam_forward = cam_forward4.swizzle<0, 1, 2>();
				tz::Vec3 cam_right = cam_right4.swizzle<0, 1, 2>();
				if(tz::window().get_keyboard_state().is_key_down(tz::KeyCode::W))
				{
					camera_position += cam_forward * multiplier;
				}
				if(tz::window().get_keyboard_state().is_key_down(tz::KeyCode::S))
				{
					camera_position -= cam_forward * multiplier;
				}
				if(tz::window().get_keyboard_state().is_key_down(tz::KeyCode::Space))
				{
					camera_position[1] += multiplier;
				}
				if(tz::window().get_keyboard_state().is_key_down(tz::KeyCode::LeftShift))
				{
					camera_position[1] -= multiplier;
				}
				if(tz::window().get_keyboard_state().is_key_down(tz::KeyCode::A))
				{
					camera_position += cam_right * multiplier;
				}
				if(tz::window().get_keyboard_state().is_key_down(tz::KeyCode::D))
				{
					camera_position -= cam_right * multiplier;
				}

			}
		}
	}
	tz::terminate();
}
<|endoftext|>


<commit_before>import java.util.Scanner;

public class MergeSort {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int day = Integer.parseInt(scanner.nextLine());
        int month = Integer.parseInt(scanner.nextLine());

        switch(month) {
            case 2:
                if (day + 5 > 28) {
                    month++;
                    day = day + 5 - 28;
                }
                else {
                    day += 5;
                }
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                if (day + 5 > 30) {
                    month++;
                    day = day + 5 - 30;
                }
                else {
                    day += 5;
                }
                break;
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
                if (day + 5 > 31) {
                    month++;
                    day = day + 5 - 31;
                }
                else {
                    day += 5;
                }
                break;
            case 12:
                if (day + 5 > 31) {
                    month = 1;
                    day = day + 5 - 31;
                }
                else {
                    day += 5;
                }
                break;
            default:
                break;
        }

        System.out.print(day + ".");
        if (month < 10) {
            System.out.print("0");
        }
        System.out.print(month);
    }
}
<commit_msg>Update 05.DateAfter5Days.cpp<commit_after>import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int day = Integer.parseInt(scanner.nextLine());
        int month = Integer.parseInt(scanner.nextLine());

        switch(month) {
            case 2:
                if (day + 5 > 28) {
                    month++;
                    day = day + 5 - 28;
                }
                else {
                    day += 5;
                }
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                if (day + 5 > 30) {
                    month++;
                    day = day + 5 - 30;
                }
                else {
                    day += 5;
                }
                break;
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
                if (day + 5 > 31) {
                    month++;
                    day = day + 5 - 31;
                }
                else {
                    day += 5;
                }
                break;
            case 12:
                if (day + 5 > 31) {
                    month = 1;
                    day = day + 5 - 31;
                }
                else {
                    day += 5;
                }
                break;
            default:
                break;
        }

        System.out.print(day + ".");
        if (month < 10) {
            System.out.print("0");
        }
        System.out.print(month);
    }
}
<|endoftext|>


<commit_before>#include "paintarea.h"

#define STARTING_X 10

//Padding from the right side of the window
#define RIGHT_SIDE_PADDING 50
#define STARTING_Y 10

PaintArea::PaintArea(QWidget *parent) :
    QWidget(parent)
{
    currentX = STARTING_X;
    currentY = STARTING_Y;
    totalWidth = 0;

    webpage = new Document;
    positionSet = false;

    currentCharacter = new QString;

    nextWordChecked = false;
}

void PaintArea::setDocument(Document *documentToSet)
{
    webpage = documentToSet;
}

void PaintArea::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    if (webpage->getFirstNode() != NULL)
    {

        QPainter qPainter(this);
        paintNodesVector = webpage->getFirstNode()->getPaintNodes();
        drawDocument(&qPainter, paintNodesVector);

        //Prevents document from moving around while being redrawn.
        positionSet = true;

        //This is necessary to show the entire paint area in the scroll area.
        setMinimumHeight(currentY);
    }
}

void PaintArea::drawDocument(QPainter *qPainter,
                             std::vector<PaintNode*> *paintNodes)
{
    std::vector<PaintNode*>::iterator i = paintNodes->begin();

    for (; i != paintNodes->end(); i++)
    {
        paintCurrentNode(*i, qPainter, paintNodes);
    }
}

void PaintArea::insertLineBreak()
{
    QFont font = currentFont;
    QFontMetrics fm(font);

    currentX = STARTING_X;
    currentY += 2 * fm.height();
    totalWidth = 0;
}

void PaintArea::paintCurrentNode(PaintNode *currentPaintNode,
                                 QPainter *qPainter,
                                 std::vector<PaintNode*> *paintNodes)
{
    if (currentPaintNode->getTypeOfPaintNode() == "char")
    {
        //Draw the text contained within each paragraph node. New lines are
        //only added after each paragraph node--not any other element.
        if (positionSet)
        {
            updateCurrentPosition();
        }

        char *character = currentPaintNode->getCharacter();
        *currentCharacter = QString(*character);

        currentFont = qPainter->font();

        if (currentPaintNode->getWeight() == QFont::Bold)
        {
            currentFont.setBold(true);
        }
        else
        {
            currentFont.setBold(false);
        }

        QFontMetrics fm(currentFont);

        if (!nextWordChecked)
        {
            if (totalWidth >= this->width() - 200)
            {
                int currentLineWidth = totalWidth;
                currentLineWidth += getNextWordWidth(paintNodes, qPainter);

                if (currentLineWidth + STARTING_X >= this->width() - RIGHT_SIDE_PADDING)
                {
                    totalWidth = 0;
                    currentY += fm.height();
                    currentX = STARTING_X;
                }

                nextWordChecked = true;
            }
        }

        QRect box(QPoint(currentX, currentY), QSize(fm.width(*character),
                                                    fm.height()));

        qPainter->setFont(currentFont);
        qPainter->drawText(box, Qt::AlignCenter, QString(*character));

        if (isspace(*character))
        {
            nextWordChecked = false;
        }

        updateCurrentPosition();
    }

    else if (currentPaintNode->getTypeOfPaintNode() == "node")
    {
        //Call the function again on each of the PaintNode's child paint nodes.
        //This ensures that all of the child nodes of the overall parent node
        //are drawn.
        std::vector<PaintNode*> *childPaintNodes = currentPaintNode->
                returnNode()->getPaintNodes();
        drawDocument(qPainter, childPaintNodes);
        if (currentPaintNode->returnNode()->getTypeOfRenderNode() == "p")
        {
            insertLineBreak();
        }
    }
}

//This adjusts the location where the next character will be drawn, including
//changing lines when the total length exceeds the width of the window.
void PaintArea::updateCurrentPosition()
{

    //positionSet is only true when the entire text has been drawn.
    //If it is false, then it is safe to set the character to the spot
    //after the current character.
    if (!positionSet)
    {
        QFontMetrics fm(currentFont);

        totalWidth += fm.width(*currentCharacter);
        currentX += fm.width(*currentCharacter);

        if (totalWidth + STARTING_X >= this->width())
        {
            setMinimumWidth(totalWidth + STARTING_X);
        }
    }

    //However, if positionSet is true, then it is time to draw the entire
    //document again, so we reset the current position to the initial state.
    else
    {
        currentX = STARTING_X;
        currentY = STARTING_Y;
        totalWidth = 0;
        positionSet = false;
    }
}

int PaintArea::getNextWordWidth(std::vector<PaintNode*> *paintNodes, QPainter *qPainter)
{
    int wordWidth = 0;
    bool wordEndReached = false;

    std::vector<PaintNode*>::iterator currentNode = paintNodes->begin();

    for (; !wordEndReached; currentNode++)
    {
        if (currentNode == paintNodes->end())
        {
            wordEndReached = true;
        }

        else if ((*currentNode)->getTypeOfPaintNode() == "char")
        {
            if (!isspace(*(*currentNode)->getCharacter()))
            {
                QFont font = qPainter->font();
                QFontMetrics fm(font);
                wordWidth += fm.width((*currentNode)->getCharacter());
            }
            else
            {
                wordEndReached = true;
            }
        }

        else if ((*currentNode)->getTypeOfPaintNode() == "node")
        {
            wordWidth += getNextWordWidth(paintNodes, qPainter);
        }
    }

    return wordWidth;
}
<commit_msg>Fix bug with text not shrinking to match resized window.<commit_after>#include "paintarea.h"

#define STARTING_X 10

//Padding from the right side of the window
#define RIGHT_SIDE_PADDING 50
#define STARTING_Y 10

PaintArea::PaintArea(QWidget *parent) :
    QWidget(parent)
{
    currentX = STARTING_X;
    currentY = STARTING_Y;
    totalWidth = 0;

    webpage = new Document;
    positionSet = false;

    currentCharacter = new QString;

    nextWordChecked = false;
}

void PaintArea::setDocument(Document *documentToSet)
{
    webpage = documentToSet;
}

void PaintArea::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    if (webpage->getFirstNode() != NULL)
    {

        QPainter qPainter(this);
        paintNodesVector = webpage->getFirstNode()->getPaintNodes();
        drawDocument(&qPainter, paintNodesVector);

        //Prevents document from moving around while being redrawn.
        positionSet = true;

        //This is necessary to show the entire paint area in the scroll area.
        setMinimumHeight(currentY);
    }
}

void PaintArea::drawDocument(QPainter *qPainter,
                             std::vector<PaintNode*> *paintNodes)
{
    std::vector<PaintNode*>::iterator i = paintNodes->begin();

    for (; i != paintNodes->end(); i++)
    {
        paintCurrentNode(*i, qPainter, paintNodes);
    }
}

void PaintArea::insertLineBreak()
{
    QFont font = currentFont;
    QFontMetrics fm(font);

    currentX = STARTING_X;
    currentY += 2 * fm.height();
    totalWidth = 0;
}

void PaintArea::paintCurrentNode(PaintNode *currentPaintNode,
                                 QPainter *qPainter,
                                 std::vector<PaintNode*> *paintNodes)
{
    if (currentPaintNode->getTypeOfPaintNode() == "char")
    {
        //Draw the text contained within each paragraph node. New lines are
        //only added after each paragraph node--not any other element.
        if (positionSet)
        {
            updateCurrentPosition();
        }

        char *character = currentPaintNode->getCharacter();
        *currentCharacter = QString(*character);

        currentFont = qPainter->font();

        if (currentPaintNode->getWeight() == QFont::Bold)
        {
            currentFont.setBold(true);
        }
        else
        {
            currentFont.setBold(false);
        }

        QFontMetrics fm(currentFont);

        if (!nextWordChecked)
        {
            if (totalWidth >= this->width() - 200)
            {
                int currentLineWidth = totalWidth;
                currentLineWidth += getNextWordWidth(paintNodes, qPainter);

                if (currentLineWidth + STARTING_X >= this->width() - RIGHT_SIDE_PADDING)
                {
                    totalWidth = 0;
                    currentY += fm.height();
                    currentX = STARTING_X;
                }

                nextWordChecked = true;
            }
        }

        QRect box(QPoint(currentX, currentY), QSize(fm.width(*character),
                                                    fm.height()));

        qPainter->setFont(currentFont);
        qPainter->drawText(box, Qt::AlignCenter, QString(*character));

        if (isspace(*character))
        {
            nextWordChecked = false;
        }

        updateCurrentPosition();
    }

    else if (currentPaintNode->getTypeOfPaintNode() == "node")
    {
        //Call the function again on each of the PaintNode's child paint nodes.
        //This ensures that all of the child nodes of the overall parent node
        //are drawn.
        std::vector<PaintNode*> *childPaintNodes = currentPaintNode->
                returnNode()->getPaintNodes();
        drawDocument(qPainter, childPaintNodes);
        if (currentPaintNode->returnNode()->getTypeOfRenderNode() == "p")
        {
            insertLineBreak();
        }
    }
}

//This adjusts the location where the next character will be drawn, including
//changing lines when the total length exceeds the width of the window.
void PaintArea::updateCurrentPosition()
{

    //positionSet is only true when the entire text has been drawn.
    //If it is false, then it is safe to set the character to the spot
    //after the current character.
    if (!positionSet)
    {
        QFontMetrics fm(currentFont);

        totalWidth += fm.width(*currentCharacter);
        currentX += fm.width(*currentCharacter);
    }

    //However, if positionSet is true, then it is time to draw the entire
    //document again, so we reset the current position to the initial state.
    else
    {
        currentX = STARTING_X;
        currentY = STARTING_Y;
        totalWidth = 0;
        positionSet = false;
    }
}

int PaintArea::getNextWordWidth(std::vector<PaintNode*> *paintNodes, QPainter *qPainter)
{
    int wordWidth = 0;
    bool wordEndReached = false;

    std::vector<PaintNode*>::iterator currentNode = paintNodes->begin();

    for (; !wordEndReached; currentNode++)
    {
        if (currentNode == paintNodes->end())
        {
            wordEndReached = true;
        }

        else if ((*currentNode)->getTypeOfPaintNode() == "char")
        {
            if (!isspace(*(*currentNode)->getCharacter()))
            {
                QFont font = qPainter->font();
                QFontMetrics fm(font);
                wordWidth += fm.width((*currentNode)->getCharacter());
            }
            else
            {
                wordEndReached = true;
            }
        }

        else if ((*currentNode)->getTypeOfPaintNode() == "node")
        {
            wordWidth += getNextWordWidth(paintNodes, qPainter);
        }
    }

    return wordWidth;
}
<|endoftext|>


<commit_before>/**
 * Copyright 2014, Planet Labs, 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 <algorithm>

#include "compositor.h"

/************************************************************************/
/*                          PercentileQuality                           */
/************************************************************************/

class PercentileQuality : public QualityMethodBase
{
    PLCInput *input;
    std::vector<float> targetQuality;
    double percentileRatio;

public:
    PercentileQuality() : QualityMethodBase("percentile") {}
    ~PercentileQuality() {}

    /********************************************************************/
    QualityMethodBase *create(PLCContext* context, WJElement node) {
        PercentileQuality *obj = new PercentileQuality();

        if( node == NULL )
        {
            CPLString default_percentile;
            if( EQUAL(context->getStratParam("compositor", "quality"),
                      "median") )
                default_percentile = "50";
            else
                default_percentile = "100";

            // 50 is true median, 100 is best quality, 0 is worst quality.
            obj->percentileRatio = atof(
                context->getStratParam("quality_percentile",
                                       default_percentile)) / 100.0;

            // median_ratio is here for backwards compatability, quality_percentile
            // Eventually it should be removed.
            if( context->getStratParam("median_ratio", NULL) != NULL )
                obj->percentileRatio = atof(context->getStratParam("median_ratio", NULL));

            CPLDebug("PLC", "Percentile quality in effect, ratio=%.3f",
                     obj->percentileRatio);
        }
        else
        {
            obj->percentileRatio = WJEDouble(node, "quality_percentile",
                                             WJE_GET, 50.0) / 100.0;
        }
        return obj;
    }

    /********************************************************************/
    void mergeQuality(PLCInput *input, PLCLine *line) {
        float *quality = line->getQuality();
        float *newQuality = line->getNewQuality();

        // In this case we copy the new quality over the old since it already incorporates
        // the old.
        for(int i=0; i < line->getWidth(); i++)
        {
            quality[i] = newQuality[i];
            newQuality[i] = 1.0;
        }
    }

    /********************************************************************/
    int computeQuality(PLCInput *input, PLCLine *lineObj) {
        float *newQuality = lineObj->getNewQuality();
        float *oldQuality = lineObj->getQuality();

        for(int i=lineObj->getWidth()-1; i >= 0; i--)
        {
            if( oldQuality[i] <= 0 )
                newQuality[i] = -1;
            else
                newQuality[i] = 1.0 - fabs(oldQuality[i] - targetQuality[i]); // rescale?
        }

        return TRUE;
    }

    /********************************************************************/
    int computeStackQuality(PLCContext *context, std::vector<PLCLine*>& lines) {

        unsigned int i;
        std::vector<float*> inputQualities;

        targetQuality.resize(context->width);

        for(i = 0; i < context->inputFiles.size(); i++ )
            inputQualities.push_back(lines[i]->getQuality());

        std::vector<float> pixelQualities;
        pixelQualities.resize(context->width);

        for(int iPixel=0; iPixel < context->width; iPixel++)
        {
            int activeCandidates = 0;

            for(i=0; i < inputQualities.size(); i++)
            {
                if( inputQualities[i][iPixel] > 0.0 )
                    pixelQualities[activeCandidates++] = inputQualities[i][iPixel];
            }

            if( activeCandidates > 1 )
            {
                std::sort(pixelQualities.begin(),
                          pixelQualities.begin()+activeCandidates);

                int bestCandidate =
                    MAX(0,MIN(activeCandidates-1,
                              ((int) floor(activeCandidates*percentileRatio))));
                targetQuality[iPixel] = pixelQualities[bestCandidate];

            }
            else if( activeCandidates == 1 )
                targetQuality[iPixel] = pixelQualities[0];
            else
                targetQuality[iPixel] = -1.0;
        }

        return QualityMethodBase::computeStackQuality(context, lines);
    }
};

static PercentileQuality percentileQualityTemplateInstance;

<commit_msg>debug output for percentile value added<commit_after>/**
 * Copyright 2014, Planet Labs, 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 <algorithm>

#include "compositor.h"

/************************************************************************/
/*                          PercentileQuality                           */
/************************************************************************/

class PercentileQuality : public QualityMethodBase
{
    PLCInput *input;
    std::vector<float> targetQuality;
    double percentileRatio;

public:
    PercentileQuality() : QualityMethodBase("percentile") {}
    ~PercentileQuality() {}

    /********************************************************************/
    QualityMethodBase *create(PLCContext* context, WJElement node) {
        PercentileQuality *obj = new PercentileQuality();

        if( node == NULL )
        {
            CPLString default_percentile;
            if( EQUAL(context->getStratParam("compositor", "quality"),
                      "median") )
                default_percentile = "50";
            else
                default_percentile = "100";

            // 50 is true median, 100 is best quality, 0 is worst quality.
            obj->percentileRatio = atof(
                context->getStratParam("quality_percentile",
                                       default_percentile)) / 100.0;

            // median_ratio is here for backwards compatability, quality_percentile
            // Eventually it should be removed.
            if( context->getStratParam("median_ratio", NULL) != NULL )
                obj->percentileRatio = atof(context->getStratParam("median_ratio", NULL));

            CPLDebug("PLC", "Percentile quality in effect, ratio=%.3f",
                     obj->percentileRatio);
        }
        else
        {
            obj->percentileRatio = WJEDouble(node, "quality_percentile",
                                             WJE_GET, 50.0) / 100.0;
            CPLDebug("PLC", "Percentile Quality: %.2f.", obj->percentileRatio);
        }
        return obj;
    }

    /********************************************************************/
    void mergeQuality(PLCInput *input, PLCLine *line) {
        float *quality = line->getQuality();
        float *newQuality = line->getNewQuality();

        // In this case we copy the new quality over the old since it already incorporates
        // the old.
        for(int i=0; i < line->getWidth(); i++)
        {
            quality[i] = newQuality[i];
            newQuality[i] = 1.0;
        }
    }

    /********************************************************************/
    int computeQuality(PLCInput *input, PLCLine *lineObj) {
        float *newQuality = lineObj->getNewQuality();
        float *oldQuality = lineObj->getQuality();

        for(int i=lineObj->getWidth()-1; i >= 0; i--)
        {
            if( oldQuality[i] <= 0 )
                newQuality[i] = -1;
            else
                newQuality[i] = 1.0 - fabs(oldQuality[i] - targetQuality[i]); // rescale?
        }

        return TRUE;
    }

    /********************************************************************/
    int computeStackQuality(PLCContext *context, std::vector<PLCLine*>& lines) {

        unsigned int i;
        std::vector<float*> inputQualities;

        targetQuality.resize(context->width);

        for(i = 0; i < context->inputFiles.size(); i++ )
            inputQualities.push_back(lines[i]->getQuality());

        std::vector<float> pixelQualities;
        pixelQualities.resize(context->width);

        for(int iPixel=0; iPixel < context->width; iPixel++)
        {
            int activeCandidates = 0;

            for(i=0; i < inputQualities.size(); i++)
            {
                if( inputQualities[i][iPixel] > 0.0 )
                    pixelQualities[activeCandidates++] = inputQualities[i][iPixel];
            }

            if( activeCandidates > 1 )
            {
                std::sort(pixelQualities.begin(),
                          pixelQualities.begin()+activeCandidates);

                int bestCandidate =
                    MAX(0,MIN(activeCandidates-1,
                              ((int) floor(activeCandidates*percentileRatio))));
                targetQuality[iPixel] = pixelQualities[bestCandidate];

            }
            else if( activeCandidates == 1 )
                targetQuality[iPixel] = pixelQualities[0];
            else
                targetQuality[iPixel] = -1.0;
        }

        return QualityMethodBase::computeStackQuality(context, lines);
    }
};

static PercentileQuality percentileQualityTemplateInstance;

<|endoftext|>


<commit_before>/* <x0/plugins/accesslog.cpp>
 *
 * This file is part of the x0 web server project and is released under LGPL-3.
 * http://www.xzero.ws/
 *
 * (c) 2009-2010 Christian Parpart <trapni@gentoo.org>
 */

#include <x0/http/HttpPlugin.h>
#include <x0/http/HttpServer.h>
#include <x0/http/HttpRequest.h>
#include <x0/http/HttpResponse.h>
#include <x0/http/HttpHeader.h>
#include <x0/strutils.h>
#include <x0/Types.h>

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

#include <cerrno>

/**
 * \ingroup plugins
 * \brief implements an accesslog log facility - in spirit of "combined" mode of apache's accesslog logs.
 */
class accesslog_plugin :
	public x0::HttpPlugin
{
private:
	x0::HttpServer::RequestPostHook::Connection c;

	struct context : public x0::ScopeValue
	{
		std::string filename_;
		int fd_;

		context() :
			filename_(),
			fd_(-1)
		{
		}

		~context()
		{
			close();
		}

		std::error_code open(const std::string& filename)
		{
			if (fd_ >= 0)
				::close(fd_);

			fd_ = ::open(filename.c_str(), O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644);
			if (fd_ < 0)
				return std::make_error_code(static_cast<std::errc>(errno));

			filename_ = filename;
			return std::error_code();
		}

		void write(const std::string message)
		{
			if (fd_ < 0)
				return;

			int rv = ::write(fd_, message.c_str(), message.size());

			if (rv < 0)
				DEBUG("Couldn't write to accesslog(%s): %s", filename_.c_str(), strerror(errno));
		}

		void close()
		{
			if (fd_ >= 0)
			{
				::close(fd_);
				fd_ = -1;
			}
		}

		void reopen()
		{
			close();
			open(filename_);
		}

		virtual void merge(const x0::ScopeValue *value)
		{
			if (auto cx = dynamic_cast<const context *>(value))
			{
				if (filename_.empty())
				{
					filename_ = cx->filename_;
					reopen();
				}
			}
		}
	};

public:
	accesslog_plugin(x0::HttpServer& srv, const std::string& name) :
		x0::HttpPlugin(srv, name)
	{
		using namespace std::placeholders;
		c = srv.onRequestDone.connect<accesslog_plugin, &accesslog_plugin::request_done>(this);

		declareCVar("AccessLog", x0::HttpContext::server | x0::HttpContext::host, &accesslog_plugin::setup_log);
	}

	~accesslog_plugin()
	{
		server_.onRequestDone.disconnect(c);
	}

private:
	std::error_code setup_log(const x0::SettingsValue& cvar, x0::Scope& s)
	{
		std::string filename;

		std::error_code ec = cvar.load(filename);
		if (ec)
			return ec;

		auto cx = s.acquire<context>(this);
		ec = cx->open(filename);

		return std::error_code();
	}

	void request_done(x0::HttpRequest *in, x0::HttpResponse *out)
	{
		if (auto stream = server().resolveHost(in->hostid())->get<context>(this))
		{
			std::stringstream sstr;
			sstr << hostname(in);
			sstr << " - "; // identity as of identd
			sstr << username(in) << ' ';
			sstr << server_.now().htlog_str().c_str() << " \"";
			sstr << request_line(in) << "\" ";
			sstr << out->status << ' ';
			sstr << out->headers["Content-Length"] << ' ';
			sstr << '"' << getheader(in, "Referer") << "\" ";
			sstr << '"' << getheader(in, "User-Agent") << '"';
			sstr << std::endl;

			stream->write(sstr.str());
		}
	}

	inline context *getlogstream(x0::HttpRequest *in)
	{
		return server_.resolveHost(in->hostid())->get<context>(this);
	}

	inline std::string hostname(x0::HttpRequest *in)
	{
		std::string name = in->connection.remote_ip();
		return !name.empty() ? name : "-";
	}

	inline std::string username(x0::HttpRequest *in)
	{
		return !in->username.empty() ? in->username.str() : "-";
	}

	inline std::string request_line(x0::HttpRequest *in)
	{
		std::stringstream str;

		str << in->method.str() << ' ' << in->uri.str()
			<< " HTTP/" << in->http_version_major << '.' << in->http_version_minor;

		return str.str();
	}

	inline std::string getheader(const x0::HttpRequest *in, const std::string& name)
	{
		x0::BufferRef value(in->header(name));
		return !value.empty() ? value.str() : "-";
	}
};

X0_EXPORT_PLUGIN(accesslog);
<commit_msg>[plugins] accesslog: fixes status code logging<commit_after>/* <x0/plugins/accesslog.cpp>
 *
 * This file is part of the x0 web server project and is released under LGPL-3.
 * http://www.xzero.ws/
 *
 * (c) 2009-2010 Christian Parpart <trapni@gentoo.org>
 */

#include <x0/http/HttpPlugin.h>
#include <x0/http/HttpServer.h>
#include <x0/http/HttpRequest.h>
#include <x0/http/HttpResponse.h>
#include <x0/http/HttpHeader.h>
#include <x0/strutils.h>
#include <x0/Types.h>

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

#include <cerrno>

/**
 * \ingroup plugins
 * \brief implements an accesslog log facility - in spirit of "combined" mode of apache's accesslog logs.
 */
class accesslog_plugin :
	public x0::HttpPlugin
{
private:
	x0::HttpServer::RequestPostHook::Connection c;

	struct context : public x0::ScopeValue
	{
		std::string filename_;
		int fd_;

		context() :
			filename_(),
			fd_(-1)
		{
		}

		~context()
		{
			close();
		}

		std::error_code open(const std::string& filename)
		{
			if (fd_ >= 0)
				::close(fd_);

			fd_ = ::open(filename.c_str(), O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644);
			if (fd_ < 0)
				return std::make_error_code(static_cast<std::errc>(errno));

			filename_ = filename;
			return std::error_code();
		}

		void write(const std::string message)
		{
			if (fd_ < 0)
				return;

			int rv = ::write(fd_, message.c_str(), message.size());

			if (rv < 0)
				DEBUG("Couldn't write to accesslog(%s): %s", filename_.c_str(), strerror(errno));
		}

		void close()
		{
			if (fd_ >= 0)
			{
				::close(fd_);
				fd_ = -1;
			}
		}

		void reopen()
		{
			close();
			open(filename_);
		}

		virtual void merge(const x0::ScopeValue *value)
		{
			if (auto cx = dynamic_cast<const context *>(value))
			{
				if (filename_.empty())
				{
					filename_ = cx->filename_;
					reopen();
				}
			}
		}
	};

public:
	accesslog_plugin(x0::HttpServer& srv, const std::string& name) :
		x0::HttpPlugin(srv, name)
	{
		using namespace std::placeholders;
		c = srv.onRequestDone.connect<accesslog_plugin, &accesslog_plugin::request_done>(this);

		declareCVar("AccessLog", x0::HttpContext::server | x0::HttpContext::host, &accesslog_plugin::setup_log);
	}

	~accesslog_plugin()
	{
		server_.onRequestDone.disconnect(c);
	}

private:
	std::error_code setup_log(const x0::SettingsValue& cvar, x0::Scope& s)
	{
		std::string filename;

		std::error_code ec = cvar.load(filename);
		if (ec)
			return ec;

		auto cx = s.acquire<context>(this);
		ec = cx->open(filename);

		return std::error_code();
	}

	void request_done(x0::HttpRequest *in, x0::HttpResponse *out)
	{
		if (auto stream = server().resolveHost(in->hostid())->get<context>(this))
		{
			std::stringstream sstr;
			sstr << hostname(in);
			sstr << " - "; // identity as of identd
			sstr << username(in) << ' ';
			sstr << server_.now().htlog_str().c_str() << " \"";
			sstr << request_line(in) << "\" ";
			sstr << static_cast<int>(out->status) << ' ';
			sstr << out->headers["Content-Length"] << ' ';
			sstr << '"' << getheader(in, "Referer") << "\" ";
			sstr << '"' << getheader(in, "User-Agent") << '"';
			sstr << std::endl;

			stream->write(sstr.str());
		}
	}

	inline context *getlogstream(x0::HttpRequest *in)
	{
		return server_.resolveHost(in->hostid())->get<context>(this);
	}

	inline std::string hostname(x0::HttpRequest *in)
	{
		std::string name = in->connection.remote_ip();
		return !name.empty() ? name : "-";
	}

	inline std::string username(x0::HttpRequest *in)
	{
		return !in->username.empty() ? in->username.str() : "-";
	}

	inline std::string request_line(x0::HttpRequest *in)
	{
		std::stringstream str;

		str << in->method.str() << ' ' << in->uri.str()
			<< " HTTP/" << in->http_version_major << '.' << in->http_version_minor;

		return str.str();
	}

	inline std::string getheader(const x0::HttpRequest *in, const std::string& name)
	{
		x0::BufferRef value(in->header(name));
		return !value.empty() ? value.str() : "-";
	}
};

X0_EXPORT_PLUGIN(accesslog);
<|endoftext|>


<commit_before>#include "command.hh"
#include "common-args.hh"
#include "shared.hh"
#include "store-api.hh"
#include "eval.hh"
#include "json.hh"
#include "value-to-json.hh"

using namespace nix;

struct CmdEval : MixJSON, InstallableCommand
{
    bool raw = false;

    CmdEval()
    {
        mkFlag(0, "raw", "print strings unquoted", &raw);
    }

    std::string name() override
    {
        return "eval";
    }

    std::string description() override
    {
        return "evaluate a Nix expression";
    }

    Examples examples() override
    {
        return {
            Example{
                "To evaluate a Nix expression given on the command line:",
                "nix eval '(1 + 2)'"
            },
            Example{
                "To evaluate a Nix expression from a file or URI:",
                "nix eval -f channel:nixos-17.09 hello.name"
            },
            Example{
                "To get the current version of Nixpkgs:",
                "nix eval --raw nixpkgs.lib.nixpkgsVersion"
            },
            Example{
                "To print the store path of the Hello package:",
                "nix eval --raw nixpkgs.hello"
            },
        };
    }

    void run(ref<Store> store) override
    {
        if (raw && json)
            throw UsageError("--raw and --json are mutually exclusive");

        auto state = getEvalState();

        auto v = installable->toValue(*state);
        PathSet context;
        if (raw) {
            std::cout << state->coerceToString(noPos, *v, context);
        } else if (json) {
            JSONPlaceholder jsonOut(std::cout);
            printValueAsJSON(*state, true, *v, jsonOut, context);
        } else {
            state->forceValueDeep(*v);
            std::cout << *v << "\n";
        }
    }
};

static RegisterCommand r1(make_ref<CmdEval>());
<commit_msg>nix eval: Stop progress bar before printing the result<commit_after>#include "command.hh"
#include "common-args.hh"
#include "shared.hh"
#include "store-api.hh"
#include "eval.hh"
#include "json.hh"
#include "value-to-json.hh"
#include "progress-bar.hh"

using namespace nix;

struct CmdEval : MixJSON, InstallableCommand
{
    bool raw = false;

    CmdEval()
    {
        mkFlag(0, "raw", "print strings unquoted", &raw);
    }

    std::string name() override
    {
        return "eval";
    }

    std::string description() override
    {
        return "evaluate a Nix expression";
    }

    Examples examples() override
    {
        return {
            Example{
                "To evaluate a Nix expression given on the command line:",
                "nix eval '(1 + 2)'"
            },
            Example{
                "To evaluate a Nix expression from a file or URI:",
                "nix eval -f channel:nixos-17.09 hello.name"
            },
            Example{
                "To get the current version of Nixpkgs:",
                "nix eval --raw nixpkgs.lib.nixpkgsVersion"
            },
            Example{
                "To print the store path of the Hello package:",
                "nix eval --raw nixpkgs.hello"
            },
        };
    }

    void run(ref<Store> store) override
    {
        if (raw && json)
            throw UsageError("--raw and --json are mutually exclusive");

        auto state = getEvalState();

        auto v = installable->toValue(*state);
        PathSet context;

        stopProgressBar();

        if (raw) {
            std::cout << state->coerceToString(noPos, *v, context);
        } else if (json) {
            JSONPlaceholder jsonOut(std::cout);
            printValueAsJSON(*state, true, *v, jsonOut, context);
        } else {
            state->forceValueDeep(*v);
            std::cout << *v << "\n";
        }
    }
};

static RegisterCommand r1(make_ref<CmdEval>());
<|endoftext|>


<commit_before>#ifndef MJOLNIR_CORE_DYNAMIC_VARIABLE_HPP
#define MJOLNIR_CORE_DYNAMIC_VARIABLE_HPP
#include <mjolnir/util/make_unique.hpp>
#include <mjolnir/util/is_finite.hpp>
#include <limits>
#include <memory>

//
// Dynamic variable is a (non-) physical parameter in a system that has
// (virtual) mass, velocity and force and updated by integrator.
//
namespace mjolnir
{

template<typename realT>
struct DynamicVariableBase
{
    using real_type = realT;

    real_type x, v, f;
    real_type m, gamma;
    real_type lower, upper;

    DynamicVariableBase(real_type x_, real_type v_, real_type f_,
                        real_type m_, real_type gamma_,
                        real_type lower_, real_type upper_)
        : x(x_), v(v_), f(f_), m(m_), gamma(gamma_), lower(lower_), upper(upper_)
    {}
    virtual ~DynamicVariableBase() = default;
    virtual void update(real_type x, real_type v, real_type f) noexcept = 0;
    virtual DynamicVariableBase<real_type>* clone() const = 0;
};

// It makes `DynamicVariable`s copyable and easier to handle.
template<typename realT>
struct DynamicVariable
{
    using real_type = typename DynamicVariableBase<realT>::real_type;

    template<typename DynVar>
    explicit DynamicVariable(DynVar&& dynvar)
        : resource_(make_unique<DynamicVariableBase<real_type>>(std::forward<DynVar>(dynvar)))
    {
        static_assert(std::is_base_of<DynamicVariableBase<realT>, DynVar>::value, "");
    }

    DynamicVariable(const DynamicVariable& other)
        : resource_(other.resource_->clone())
    {}
    DynamicVariable& operator=(const DynamicVariable& other)
    {
        this->resource_.reset(other.resource_->clone());
        return *this;
    }
    DynamicVariable(DynamicVariable&&) = default;
    DynamicVariable& operator=(DynamicVariable&&) = default;
    ~DynamicVariable() = default;

    real_type x() const noexcept {return resource_->x;}
    real_type v() const noexcept {return resource_->v;}
    real_type f() const noexcept {return resource_->f;}
    real_type m() const noexcept {return resource_->m;}
    real_type gamma() const noexcept {return resource_->gamma;}

    void update(real_type x, real_type v, real_type f) const noexcept
    {
        resource_->update(x, v, f);
    }

  private:
    std::unique_ptr<DynamicVariableBase<realT>> resource_;
};

template<typename realT>
struct DefaultDynamicVariable : public DynamicVariableBase<realT>
{
    using base_type = DynamicVariableBase<realT>;
    using real_type = typename base_type::real_type;

    DefaultDynamicVariable(const real_type x, const real_type v, const real_type f,
                           const real_type m, const real_type gamma)
        : base_type{x, v, f, m, gamma,
                    -std::numeric_limits<real_type>::infinity(),
                     std::numeric_limits<real_type>::infinity()}
    {}
    ~DefaultDynamicVariable() override = default;

    void update(real_type x, real_type v, real_type f) noexcept override
    {
        this->x = x;
        this->v = v;
        this->f = f;
        return;
    }
    DynamicVariableBase<real_type>* clone() const override
    {
        return new DefaultDynamicVariable(*this);
    }
};

template<typename realT>
struct PeriodicDynamicVariable : public DynamicVariableBase<realT>
{
    using base_type = DynamicVariableBase<realT>;
    using real_type = typename base_type::real_type;

    PeriodicDynamicVariable(const real_type x, const real_type v, const real_type f,
                            const real_type m, const real_type gamma,
                            const real_type lower, const real_type upper)
        : base_type(x, v, f, m, gamma, lower, upper)
    {}
    ~PeriodicDynamicVariable() override = default;

    void update(real_type x, real_type v, real_type f) noexcept override
    {
        this->x = x;
        if      (this->x <  this->lower) {this->x += (this->upper - this->lower);}
        else if (this->upper <= this->x) {this->x -= (this->upper - this->lower);}
        this->v = v;
        this->f = f;
        return;
    }
    DynamicVariableBase<real_type>* clone() const override
    {
        return new PeriodicDynamicVariable(*this);
    }
};

template<typename realT>
struct RepulsiveDynamicVariable : public DynamicVariableBase<realT>
{
    using base_type = DynamicVariableBase<realT>;
    using real_type = typename base_type::real_type;

    RepulsiveDynamicVariable(const real_type x, const real_type v, const real_type f,
                             const real_type m, const real_type gamma,
                             const real_type lower, const real_type upper)
        : base_type(x, v, f, m, gamma, lower, upper)
    {}
    ~RepulsiveDynamicVariable() override = default;

    void update(real_type x, real_type v, real_type f) noexcept override
    {
        if(x < this->lower)
        {
            this->x = 2 * this->lower - x; // lower + (lower - x)
            this->v = -v;
        }
        else if (this->upper < x)
        {
            this->x = 2 * this->upper - x; // upper - (x - upper)
            this->v = -v;
        }
        else
        {
            this->x = x;
            this->v = v;
        }
        this->f = f;
        return;
    }
    DynamicVariableBase<real_type>* clone() const override
    {
        return new RepulsiveDynamicVariable(*this);
    }
};

#ifdef MJOLNIR_SEPARATE_BUILD
extern template class DynamicVariableBase<double>;
extern template class DynamicVariableBase<float >;
extern template class DynamicVariable<double>;
extern template class DynamicVariable<float >;
extern template class DefaultDynamicVariable<double>;
extern template class DefaultDynamicVariable<float >;
extern template class PeriodicDynamicVariable<double>;
extern template class PeriodicDynamicVariable<float >;
extern template class RepulsiveDynamicVariable<double>;
extern template class RepulsiveDynamicVariable<float >;
#endif

} // mjolnir
#endif// MJOLNIR_CORE_DYNAMIC_VARIABLE_HPP
<commit_msg>feat: add default ctor to dynvar<commit_after>#ifndef MJOLNIR_CORE_DYNAMIC_VARIABLE_HPP
#define MJOLNIR_CORE_DYNAMIC_VARIABLE_HPP
#include <mjolnir/util/make_unique.hpp>
#include <mjolnir/util/is_finite.hpp>
#include <limits>
#include <memory>

//
// Dynamic variable is a (non-) physical parameter in a system that has
// (virtual) mass, velocity and force and updated by integrator.
//
namespace mjolnir
{

template<typename realT>
struct DynamicVariableBase
{
    using real_type = realT;

    real_type x, v, f;
    real_type m, gamma;
    real_type lower, upper;

    DynamicVariableBase(real_type x_, real_type v_, real_type f_,
                        real_type m_, real_type gamma_,
                        real_type lower_, real_type upper_)
        : x(x_), v(v_), f(f_), m(m_), gamma(gamma_), lower(lower_), upper(upper_)
    {}
    virtual ~DynamicVariableBase() = default;
    virtual void update(real_type x, real_type v, real_type f) noexcept = 0;
    virtual DynamicVariableBase<real_type>* clone() const = 0;
};

// It makes `DynamicVariable`s copyable and easier to handle.
template<typename realT>
struct DynamicVariable
{
    using real_type = typename DynamicVariableBase<realT>::real_type;

    template<typename DynVar>
    explicit DynamicVariable(DynVar&& dynvar)
        : resource_(make_unique<DynamicVariableBase<real_type>>(std::forward<DynVar>(dynvar)))
    {
        static_assert(std::is_base_of<DynamicVariableBase<realT>, DynVar>::value, "");
    }
    DynamicVariable(): resource_(nullptr) {}

    DynamicVariable(const DynamicVariable& other)
        : resource_(other.resource_->clone())
    {}
    DynamicVariable& operator=(const DynamicVariable& other)
    {
        this->resource_.reset(other.resource_->clone());
        return *this;
    }
    DynamicVariable(DynamicVariable&&) = default;
    DynamicVariable& operator=(DynamicVariable&&) = default;
    ~DynamicVariable() = default;

    real_type x() const noexcept {return resource_->x;}
    real_type v() const noexcept {return resource_->v;}
    real_type f() const noexcept {return resource_->f;}
    real_type m() const noexcept {return resource_->m;}
    real_type gamma() const noexcept {return resource_->gamma;}

    void update(real_type x, real_type v, real_type f) const noexcept
    {
        resource_->update(x, v, f);
    }

  private:
    std::unique_ptr<DynamicVariableBase<realT>> resource_;
};

template<typename realT>
struct DefaultDynamicVariable : public DynamicVariableBase<realT>
{
    using base_type = DynamicVariableBase<realT>;
    using real_type = typename base_type::real_type;

    DefaultDynamicVariable(const real_type x, const real_type v, const real_type f,
                           const real_type m, const real_type gamma)
        : base_type{x, v, f, m, gamma,
                    -std::numeric_limits<real_type>::infinity(),
                     std::numeric_limits<real_type>::infinity()}
    {}
    ~DefaultDynamicVariable() override = default;

    void update(real_type x, real_type v, real_type f) noexcept override
    {
        this->x = x;
        this->v = v;
        this->f = f;
        return;
    }
    DynamicVariableBase<real_type>* clone() const override
    {
        return new DefaultDynamicVariable(*this);
    }
};

template<typename realT>
struct PeriodicDynamicVariable : public DynamicVariableBase<realT>
{
    using base_type = DynamicVariableBase<realT>;
    using real_type = typename base_type::real_type;

    PeriodicDynamicVariable(const real_type x, const real_type v, const real_type f,
                            const real_type m, const real_type gamma,
                            const real_type lower, const real_type upper)
        : base_type(x, v, f, m, gamma, lower, upper)
    {}
    ~PeriodicDynamicVariable() override = default;

    void update(real_type x, real_type v, real_type f) noexcept override
    {
        this->x = x;
        if      (this->x <  this->lower) {this->x += (this->upper - this->lower);}
        else if (this->upper <= this->x) {this->x -= (this->upper - this->lower);}
        this->v = v;
        this->f = f;
        return;
    }
    DynamicVariableBase<real_type>* clone() const override
    {
        return new PeriodicDynamicVariable(*this);
    }
};

template<typename realT>
struct RepulsiveDynamicVariable : public DynamicVariableBase<realT>
{
    using base_type = DynamicVariableBase<realT>;
    using real_type = typename base_type::real_type;

    RepulsiveDynamicVariable(const real_type x, const real_type v, const real_type f,
                             const real_type m, const real_type gamma,
                             const real_type lower, const real_type upper)
        : base_type(x, v, f, m, gamma, lower, upper)
    {}
    ~RepulsiveDynamicVariable() override = default;

    void update(real_type x, real_type v, real_type f) noexcept override
    {
        if(x < this->lower)
        {
            this->x = 2 * this->lower - x; // lower + (lower - x)
            this->v = -v;
        }
        else if (this->upper < x)
        {
            this->x = 2 * this->upper - x; // upper - (x - upper)
            this->v = -v;
        }
        else
        {
            this->x = x;
            this->v = v;
        }
        this->f = f;
        return;
    }
    DynamicVariableBase<real_type>* clone() const override
    {
        return new RepulsiveDynamicVariable(*this);
    }
};

#ifdef MJOLNIR_SEPARATE_BUILD
extern template class DynamicVariableBase<double>;
extern template class DynamicVariableBase<float >;
extern template class DynamicVariable<double>;
extern template class DynamicVariable<float >;
extern template class DefaultDynamicVariable<double>;
extern template class DefaultDynamicVariable<float >;
extern template class PeriodicDynamicVariable<double>;
extern template class PeriodicDynamicVariable<float >;
extern template class RepulsiveDynamicVariable<double>;
extern template class RepulsiveDynamicVariable<float >;
#endif

} // mjolnir
#endif// MJOLNIR_CORE_DYNAMIC_VARIABLE_HPP
<|endoftext|>


<commit_before>// Copyright (c) 2011-2012, Zeex
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. 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.
//
// 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 "os.h"

#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>

#include <cxxabi.h>
#include <dirent.h>
#include <execinfo.h>
#include <fnmatch.h>

#ifndef _GNU_SOURCE
	#define _GNU_SOURCE 1 // for dladdr()
#endif
#include <dlfcn.h>

const char os::kDirSepChar = '/';

std::string os::GetModulePath(void *address, std::size_t maxLength) {
	std::vector<char> name(maxLength + 1);
	if (address != 0) {
		Dl_info info;
		dladdr(address, &info);
		strncpy(name.data(), info.dli_fname, maxLength);
	}
	return std::string(name.data());
}

// The crash handler - it is set via SetCrashHandler()
static void (*crashHandler)() = 0;

// Previous SIGSEGV handler
static void (*previousSIGSEGVHandler)(int);

static void HandleSIGSEGV(int sig)
{
	if (::crashHandler != 0) {
		::crashHandler();
	}
	signal(sig, SIG_DFL);
}

void os::SetCrashHandler(void (*handler)()) {
	::crashHandler = handler;
	if (handler != 0) {
		::previousSIGSEGVHandler = signal(SIGSEGV, HandleSIGSEGV);
	} else {
		signal(SIGSEGV, ::previousSIGSEGVHandler);
	}
}

// The interrupt (Ctrl+C) handler - set via SetInterruptHandler
static void (*interruptHandler)();

// Previous SIGINT handler
static void (*previousSIGINTHandler)(int);

// Out SIGINT handler
static void HandleSIGINT(int sig) {
	if (::interruptHandler != 0) {
		::interruptHandler();
	}
	signal(sig, ::previousSIGINTHandler);
	raise(sig);
}

void os::SetInterruptHandler(void (*handler)()) {
	::interruptHandler = handler;
	::previousSIGINTHandler = signal(SIGINT, HandleSIGINT);
}

std::string os::GetSymbolName(void *address, std::size_t maxLength) {
	char **symbols = backtrace_symbols(&address, 1);
	std::string symbol(symbols[0]);
	std::free(symbols);

	std::string::size_type lp = symbol.find('(');
	std::string::size_type rp = symbol.find_first_of(")+-");

	std::string name;
	if (lp != std::string::npos && rp != std::string::npos) {
		name.assign(symbol.begin() + lp + 1, symbol.begin() + rp);
	}

	if (!name.empty()) {
		char *demangled_name = abi::__cxa_demangle(name.c_str(), 0, 0, 0);
		if (demangled_name != 0) {
			name.assign(demangled_name);
		}
	}

	return name;
}

void os::ListDirectoryFiles(const std::string &directory, const std::string &pattern,
		bool (*callback)(const char *, void *), void *userData)
{
	DIR *dp;
	if ((dp = opendir(directory.c_str())) != 0) {
		struct dirent *dirp;
		while ((dirp = readdir(dp)) != 0) {
			if (!fnmatch(pattern.c_str(), dirp->d_name, FNM_CASEFOLD | FNM_NOESCAPE | FNM_PERIOD)) {
				callback(dirp->d_name, userData);
			}
		}
		closedir(dp);
	}
}
<commit_msg>os-unix: Make GetSymbolName() strip type information from C++ names<commit_after>// Copyright (c) 2011-2012, Zeex
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. 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.
//
// 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 "os.h"

#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>

#include <cxxabi.h>
#include <dirent.h>
#include <execinfo.h>
#include <fnmatch.h>

#ifndef _GNU_SOURCE
	#define _GNU_SOURCE 1 // for dladdr()
#endif
#include <dlfcn.h>

const char os::kDirSepChar = '/';

std::string os::GetModulePath(void *address, std::size_t maxLength) {
	std::vector<char> name(maxLength + 1);
	if (address != 0) {
		Dl_info info;
		dladdr(address, &info);
		strncpy(name.data(), info.dli_fname, maxLength);
	}
	return std::string(name.data());
}

// The crash handler - it is set via SetCrashHandler()
static void (*crashHandler)() = 0;

// Previous SIGSEGV handler
static void (*previousSIGSEGVHandler)(int);

static void HandleSIGSEGV(int sig)
{
	if (::crashHandler != 0) {
		::crashHandler();
	}
	signal(sig, SIG_DFL);
}

void os::SetCrashHandler(void (*handler)()) {
	::crashHandler = handler;
	if (handler != 0) {
		::previousSIGSEGVHandler = signal(SIGSEGV, HandleSIGSEGV);
	} else {
		signal(SIGSEGV, ::previousSIGSEGVHandler);
	}
}

// The interrupt (Ctrl+C) handler - set via SetInterruptHandler
static void (*interruptHandler)();

// Previous SIGINT handler
static void (*previousSIGINTHandler)(int);

// Out SIGINT handler
static void HandleSIGINT(int sig) {
	if (::interruptHandler != 0) {
		::interruptHandler();
	}
	signal(sig, ::previousSIGINTHandler);
	raise(sig);
}

void os::SetInterruptHandler(void (*handler)()) {
	::interruptHandler = handler;
	::previousSIGINTHandler = signal(SIGINT, HandleSIGINT);
}

std::string os::GetSymbolName(void *address, std::size_t maxLength) {
	char **symbols = backtrace_symbols(&address, 1);
	std::string symbol(symbols[0]);
	std::free(symbols);

	std::string::size_type lp = symbol.find('(');
	std::string::size_type rp = symbol.find_first_of(")+-");

	std::string name;
	if (lp != std::string::npos && rp != std::string::npos) {
		name.assign(symbol.begin() + lp + 1, symbol.begin() + rp);
	}

	if (!name.empty()) {
		char *demangled_name = abi::__cxa_demangle(name.c_str(), 0, 0, 0);
		if (demangled_name != 0) {
			name.assign(demangled_name);

			// Cut argment type information e.g. (int*, char*, void*).
			std::string::size_type end = name.find('(');
			if (end != std::string::npos) {
				name.erase(end);
			}
		}
	}

	return name;
}

void os::ListDirectoryFiles(const std::string &directory, const std::string &pattern,
		bool (*callback)(const char *, void *), void *userData)
{
	DIR *dp;
	if ((dp = opendir(directory.c_str())) != 0) {
		struct dirent *dirp;
		while ((dirp = readdir(dp)) != 0) {
			if (!fnmatch(pattern.c_str(), dirp->d_name, FNM_CASEFOLD | FNM_NOESCAPE | FNM_PERIOD)) {
				callback(dirp->d_name, userData);
			}
		}
		closedir(dp);
	}
}
<|endoftext|>