<commit_before>#include <iostream>
#include <fstream>
//#include <codecvt>
//#include <cstddef>
#include <locale>
#include <string>
#include <iomanip>

#include "cp-neural.h"

using std::wcout; using std::wstring;
using std::cerr;

class Text {
private:
    bool isinit=false;
    bool readDataFile(string inputfile) {
        std::wifstream txtfile(inputfile, std::ios::binary);
        if (!txtfile.is_open()) {
            return false;
        }
        txtfile.imbue(std::locale("en_US.UTF8"));
        wstring ttext((std::istreambuf_iterator<wchar_t>(txtfile)),
                     std::istreambuf_iterator<wchar_t>());
        txtfile.close();
        text=ttext;
        filename=inputfile;
        return true;
    }
public:
    wstring text;
    string filename;
    std::map<wchar_t,int> freq;
    std::map<wchar_t,int> w2v;
    std::map<int,wchar_t> v2w;
    Text(string filename) {
        if (readDataFile(filename)) {
            for (auto wc : text) {
                freq[wc]++;
            }
            int it=0;
            for (auto wc : freq) {
                w2v[wc.first]=it;
                v2w[it]=wc.first;
                ++it;
            }
            isinit=true;
            cerr << "Freq:" << freq.size() << ", w2v:" << w2v.size() << ", v2w:" << v2w.size() << endl;
        }
    }
    ~Text() {

    }
    bool isInit() {
        return isinit;
    }
    int vocsize() {
        if (!isinit) return 0;
        return v2w.size();
    }
};

int main(int argc, char *argv[]) {
    std::setlocale (LC_ALL, "");
    wcout << L"Rnn-Readär" << std::endl;

    bool allOk=true;
    if (argc!=2) {
        cerr << "rnnreader <path-to-text-file>" << endl;
        exit(-1);
    }
    Text txt(argv[1]);
    if (!txt.isInit()) {
        cerr << "Cannot initialize Text object from inputfile: " << argv[1] << endl;
        exit(-1);
    }

    wcout << L"Text size: " << txt.text.size() << endl;

    wcout << L"Size of vocabulary:" << txt.freq.size() << std::endl;
/*    for (auto f : txt.freq) {
        int c=(int)f.first;
        wstring wc(1,f.first);
        wcout << wc << L"|" <<  wchar_t(f.first) << L"(0x" << std::hex << c << L")" ": " << std::dec <<  f.second << endl;
    }
*/
    Color::Modifier red(Color::FG_RED);
    Color::Modifier green(Color::FG_GREEN);
    Color::Modifier def(Color::FG_DEFAULT);

    int T=1; //32;
    int N=txt.text.size()-T+1;

    MatrixN Xr(N,T);
    MatrixN yr(N,T);

    wstring chunk,chunky;
    for (int i=0; i<N-T; i++) {
        for (int t=0; t<T; t++) {
            chunk=txt.text.substr(i+t,T);
            chunky=txt.text.substr(i+t+1,T);
            Xr(i,t)=txt.w2v[chunk[t]];
            yr(i,t)=txt.w2v[chunky[t]];
        }
    }

    MatrixN X(1000000,T);
    MatrixN y(1000000,T);
    MatrixN Xv(100000,T);
    MatrixN yv(100000,T);
    MatrixN Xt(100000,T);
    MatrixN yt(100000,T);

/*    X=Xr.block(0,0,1000000,T);
    y=yr.block(0,0,1000000,T);
    Xv=Xr.block(1000000,0,100000,T);
    yv=yr.block(1000000,0,100000,T);
    Xt=Xr.block(1100000,0,100000,T);
    yt=yr.block(1100000,0,100000,T);
*/
    X=Xr.block(0,0,10000,T);
    y=yr.block(0,0,10000,T);
    Xv=Xr.block(11000,0,1000,T);
    yv=yr.block(12000,0,1000,T);
    Xt=Xr.block(12000,0,1000,T);
    yt=yr.block(12000,0,1000,T);

    cpInitCompute("Rnnreader");
    registerLayers();

    LayerBlock lb("{name='rnnreader';init='normal'}");
    int VS=txt.vocsize();
    int H=1024;
    int D=16;
    int BS=128;

    CpParams cp0;
    cp0.setPar("inputShape",vector<int>{T});
    cp0.setPar("V",VS);
    cp0.setPar("D",D);
    lb.addLayer("WordEmbedding","WE0",cp0,{"input"});

    CpParams cp1;
    cp1.setPar("inputShape",vector<int>{D,T});
    //cp1.setPar("T",T);
    cp1.setPar("N",BS);
    cp1.setPar("H",H);
    cp1.setPar("maxcut",(float)5.0);
    lb.addLayer("RNN","rnn1",cp1,{"WE0"});
/*
    CpParams cp2;
    cp2.setPar("inputShape",vector<int>{H,T});
    //cp1.setPar("T",T);
    cp2.setPar("N",BS);
    cp2.setPar("H",H);
    lb.addLayer("RNN","rnn2",cp2,{"rnn1"});

    CpParams cp3;
    cp3.setPar("inputShape",vector<int>{H,T});
    //cp1.setPar("T",T);
    cp3.setPar("N",BS);
    cp3.setPar("H",H);
    lb.addLayer("RNN","rnn3",cp3,{"rnn2"});
*/
    CpParams cp10;
    cp10.setPar("inputShape",vector<int>{H,T});
    //cp10.setPar("T",T);
    //cp10.setPar("D",H);
    cp10.setPar("M",VS);
    lb.addLayer("TemporalAffine","af1",cp10,{"rnn1"});

    CpParams cp11;
    cp11.setPar("inputShape",vector<int>{VS,T});
    lb.addLayer("TemporalSoftmax","sm1",cp11,{"af1"});

    if (!lb.checkTopology(true)) {
        allOk=false;
        cerr << red << "Topology-check for LayerBlock: ERROR." << def << endl;
    } else {
        cerr << green << "Topology-check for LayerBlock: ok." << def << endl;
    }

/*    wstring chunk;
    chunk = txt.text.substr(512,128);
    wcout << chunk << endl;
*/
    CpParams cpo("{verbose=true;epsion=1e-8}");
    cpo.setPar("learning_rate", (floatN)2e-2); //2.2e-2);
    cpo.setPar("lr_decay", (floatN)1.0);
    cpo.setPar("regularization", (floatN)1e-5);

    cpo.setPar("epochs",(floatN)1.0);
    cpo.setPar("batch_size",BS);

    MatrixN xg(1,1);
    wstring sg;
    for (int i=0; i<100; i++) {
        /*floatN cAcc=*/lb.train(X, y, Xv, yv, "Adam", cpo);
        wstring instr=L"Er sagte";
        for (auto wc : instr) {
            sg[0]=wc;
            xg(0,0)=txt.w2v[sg[0]];
            MatrixN z(0,0);
            MatrixN yg=lb.forward(xg,z,nullptr);
        }
        for (int g=0; g<100; g++) {
            xg(0,0)=txt.w2v[sg[0]];
            MatrixN z(0,0);
            MatrixN yg=lb.forward(xg,z,nullptr);
            float mx=-1000.0;
            int ind=-1;
            for (int j=0; j<yg.cols(); j++) {
                if (yg(0,j)>mx) {
                    mx=yg(0,j);
                    ind=j;
                }
            }
            if (ind==-1) {
                cerr << "Unexpected ind:" << ind << endl;
                exit(-1);
            }
            wchar_t cw=txt.v2w[ind];
            wcout << cw;
            sg[0]=cw;
        }
        wcout << endl;
    }

    /*
    floatN train_err, val_err, test_err;
    bool evalFinal=true;
    if (evalFinal) {
        train_err=lb.test(X, y, cpo.getPar("batch_size", 50));
        val_err=lb.test(Xv, yv, cpo.getPar("batch_size", 50));
        test_err=lb.test(Xt, yt, cpo.getPar("batch_size", 50));

        cerr << "Final results on RnnReader after " << cpo.getPar("epochs",(floatN)0.0) << " epochs:" << endl;
        cerr << "      Train-error: " << train_err << " train-acc: " << 1.0-train_err << endl;
        cerr << " Validation-error: " << val_err <<   "   val-acc: " << 1.0-val_err << endl;
        cerr << "       Test-error: " << test_err <<  "  test-acc: " << 1.0-test_err << endl;
    }
    //return cAcc;
    */
    cpExitCompute();
}
<commit_msg>more training<commit_after>#include <iostream>
#include <fstream>
//#include <codecvt>
//#include <cstddef>
#include <locale>
#include <string>
#include <iomanip>

#include "cp-neural.h"

using std::wcout; using std::wstring;
using std::cerr;

class Text {
private:
    bool isinit=false;
    bool readDataFile(string inputfile) {
        std::wifstream txtfile(inputfile, std::ios::binary);
        if (!txtfile.is_open()) {
            return false;
        }
        txtfile.imbue(std::locale("en_US.UTF8"));
        wstring ttext((std::istreambuf_iterator<wchar_t>(txtfile)),
                     std::istreambuf_iterator<wchar_t>());
        txtfile.close();
        text=ttext;
        filename=inputfile;
        return true;
    }
public:
    wstring text;
    string filename;
    std::map<wchar_t,int> freq;
    std::map<wchar_t,int> w2v;
    std::map<int,wchar_t> v2w;
    Text(string filename) {
        if (readDataFile(filename)) {
            for (auto wc : text) {
                freq[wc]++;
            }
            int it=0;
            for (auto wc : freq) {
                w2v[wc.first]=it;
                v2w[it]=wc.first;
                ++it;
            }
            isinit=true;
            cerr << "Freq:" << freq.size() << ", w2v:" << w2v.size() << ", v2w:" << v2w.size() << endl;
        }
    }
    ~Text() {

    }
    bool isInit() {
        return isinit;
    }
    int vocsize() {
        if (!isinit) return 0;
        return v2w.size();
    }
};

int main(int argc, char *argv[]) {
    std::setlocale (LC_ALL, "");
    wcout << L"Rnn-Readär" << std::endl;

    bool allOk=true;
    if (argc!=2) {
        cerr << "rnnreader <path-to-text-file>" << endl;
        exit(-1);
    }
    Text txt(argv[1]);
    if (!txt.isInit()) {
        cerr << "Cannot initialize Text object from inputfile: " << argv[1] << endl;
        exit(-1);
    }

    wcout << L"Text size: " << txt.text.size() << endl;

    wcout << L"Size of vocabulary:" << txt.freq.size() << std::endl;
/*    for (auto f : txt.freq) {
        int c=(int)f.first;
        wstring wc(1,f.first);
        wcout << wc << L"|" <<  wchar_t(f.first) << L"(0x" << std::hex << c << L")" ": " << std::dec <<  f.second << endl;
    }
*/
    Color::Modifier red(Color::FG_RED);
    Color::Modifier green(Color::FG_GREEN);
    Color::Modifier def(Color::FG_DEFAULT);

    int T=1; //32;
    int N=txt.text.size()-T+1;

    MatrixN Xr(N,T);
    MatrixN yr(N,T);

    wstring chunk,chunky;
    for (int i=0; i<N-T; i++) {
        for (int t=0; t<T; t++) {
            chunk=txt.text.substr(i+t,T);
            chunky=txt.text.substr(i+t+1,T);
            Xr(i,t)=txt.w2v[chunk[t]];
            yr(i,t)=txt.w2v[chunky[t]];
        }
    }

    MatrixN X(1000000,T);
    MatrixN y(1000000,T);
    MatrixN Xv(100000,T);
    MatrixN yv(100000,T);
    MatrixN Xt(100000,T);
    MatrixN yt(100000,T);

/*    X=Xr.block(0,0,1000000,T);
    y=yr.block(0,0,1000000,T);
    Xv=Xr.block(1000000,0,100000,T);
    yv=yr.block(1000000,0,100000,T);
    Xt=Xr.block(1100000,0,100000,T);
    yt=yr.block(1100000,0,100000,T);
*/
    X=Xr.block(0,0,100000,T);
    y=yr.block(0,0,100000,T);
    Xv=Xr.block(100000,0,10000,T);
    yv=yr.block(100000,0,10000,T);
    Xt=Xr.block(110000,0,10000,T);
    yt=yr.block(110000,0,10000,T);

    cpInitCompute("Rnnreader");
    registerLayers();

    LayerBlock lb("{name='rnnreader';init='normal'}");
    int VS=txt.vocsize();
    int H=1024;
    int D=16;
    int BS=128;

    CpParams cp0;
    cp0.setPar("inputShape",vector<int>{T});
    cp0.setPar("V",VS);
    cp0.setPar("D",D);
    lb.addLayer("WordEmbedding","WE0",cp0,{"input"});

    CpParams cp1;
    cp1.setPar("inputShape",vector<int>{D,T});
    //cp1.setPar("T",T);
    cp1.setPar("N",BS);
    cp1.setPar("H",H);
    cp1.setPar("maxcut",(float)5.0);
    lb.addLayer("RNN","rnn1",cp1,{"WE0"});
/*
    CpParams cp2;
    cp2.setPar("inputShape",vector<int>{H,T});
    //cp1.setPar("T",T);
    cp2.setPar("N",BS);
    cp2.setPar("H",H);
    lb.addLayer("RNN","rnn2",cp2,{"rnn1"});

    CpParams cp3;
    cp3.setPar("inputShape",vector<int>{H,T});
    //cp1.setPar("T",T);
    cp3.setPar("N",BS);
    cp3.setPar("H",H);
    lb.addLayer("RNN","rnn3",cp3,{"rnn2"});
*/
    CpParams cp10;
    cp10.setPar("inputShape",vector<int>{H,T});
    //cp10.setPar("T",T);
    //cp10.setPar("D",H);
    cp10.setPar("M",VS);
    lb.addLayer("TemporalAffine","af1",cp10,{"rnn1"});

    CpParams cp11;
    cp11.setPar("inputShape",vector<int>{VS,T});
    lb.addLayer("TemporalSoftmax","sm1",cp11,{"af1"});

    if (!lb.checkTopology(true)) {
        allOk=false;
        cerr << red << "Topology-check for LayerBlock: ERROR." << def << endl;
    } else {
        cerr << green << "Topology-check for LayerBlock: ok." << def << endl;
    }

/*    wstring chunk;
    chunk = txt.text.substr(512,128);
    wcout << chunk << endl;
*/
    CpParams cpo("{verbose=true;epsion=1e-8}");
    cpo.setPar("learning_rate", (floatN)2e-2); //2.2e-2);
    cpo.setPar("lr_decay", (floatN)1.0);
    cpo.setPar("regularization", (floatN)1e-5);

    cpo.setPar("epochs",(floatN)5.0);
    cpo.setPar("batch_size",BS);

    MatrixN xg(1,1);
    wstring sg;
    for (int i=0; i<100; i++) {
        /*floatN cAcc=*/lb.train(X, y, Xv, yv, "Adam", cpo);
        wstring instr=L"Er sagte";
        for (auto wc : instr) {
            sg[0]=wc;
            xg(0,0)=txt.w2v[sg[0]];
            MatrixN z(0,0);
            MatrixN yg=lb.forward(xg,z,nullptr);
        }
        for (int g=0; g<100; g++) {
            xg(0,0)=txt.w2v[sg[0]];
            MatrixN z(0,0);
            MatrixN yg=lb.forward(xg,z,nullptr);
            float mx=-1000.0;
            int ind=-1;
            for (int j=0; j<yg.cols(); j++) {
                if (yg(0,j)>mx) {
                    mx=yg(0,j);
                    ind=j;
                }
            }
            if (ind==-1) {
                cerr << "Unexpected ind:" << ind << endl;
                exit(-1);
            }
            wchar_t cw=txt.v2w[ind];
            wcout << cw;
            sg[0]=cw;
        }
        wcout << endl;
    }

    /*
    floatN train_err, val_err, test_err;
    bool evalFinal=true;
    if (evalFinal) {
        train_err=lb.test(X, y, cpo.getPar("batch_size", 50));
        val_err=lb.test(Xv, yv, cpo.getPar("batch_size", 50));
        test_err=lb.test(Xt, yt, cpo.getPar("batch_size", 50));

        cerr << "Final results on RnnReader after " << cpo.getPar("epochs",(floatN)0.0) << " epochs:" << endl;
        cerr << "      Train-error: " << train_err << " train-acc: " << 1.0-train_err << endl;
        cerr << " Validation-error: " << val_err <<   "   val-acc: " << 1.0-val_err << endl;
        cerr << "       Test-error: " << test_err <<  "  test-acc: " << 1.0-test_err << endl;
    }
    //return cAcc;
    */
    cpExitCompute();
}
<|endoftext|>


<commit_before>#ifndef CglConicCutGenerator_H
#define CglConicCutGenerator_H

// CGL headers
#include <CglTreeInfo.hpp>
// OsiConic headers
#include <OsiConicSolverInterface.hpp>

// this is an abstract base class for generating conic cuts.
// specific conic cut generators inherit this class.
//
//

// what is common to all conic cut generators?
// for now we assume there is not much in common.
// I will come back here when I implemented all specific cuts
// since I will know then what is common.
// following maybe?
// --cut generating cone
// ----size of cone
// ----members of the cut generating cone
// --disjunction?

class CglConicCutGenerator {
public:
  // default constructor
  CglConicCutGenerator();
  // copy constructor
  CglConicCutGenerator(CglConicCutGenerator const & other);
  // copy assignment operator
  CglConicCutGenerator & operator=(CglConicCutGenerator const & rhs);
  virtual ~CglConicCutGenerator();
  // clone method
  virtual CglConicCutGenerator * clone() const = 0;
  // Create C++ lines so set generator, I do not see why we have this.
  virtual std::string generateCpp( FILE * ) {return "";}

  /// This can be used to refresh any information
  virtual void refreshSolver(OsiConicSolverInterface * si) {}
  // generate cuts
  virtual void generateCuts(const OsiConicSolverInterface & si,
			    OsiConicCuts & cs,
			    const CglTreeInfo info = CglTreeInfo()) = 0;
  int aggressiveness() const;
  void setAggressiveness(int value);
  // set whether can do global cuts
  void setGlobalCuts(bool ability);
  bool canDoGlobalCuts() const;
  /**
     Returns true if may generate cuts in tree (rather than root node).
     Used so know if matrix will change in tree.  Really
     meant so column cut generators can still be active
     without worrying code.
     Default is true
  */
  virtual bool mayGenerateRowCutsInTree() const;
  /// Return true if needs optimal basis to do cuts
  virtual bool needsOptimalBasis() const;
  /// Return maximum length of cut in tree
  virtual int maximumLengthOfCutInTree() const
  { return COIN_INT_MAX;}
private:
  /**
     Aggressiveness - 0 = neutral, 100 is normal root node.
     Really just a hint to cut generator
  */
  int aggressive_;
  /// True if can do global cuts i.e. no general integers
  bool canDoGlobalCuts_;
};

// we define a class to represent a disjunction. This is for conic Cgl
// use only. Not intented for public use.
class Disjunction {
  int size_;
  double * c1_;
  double c10_;
  double * c2_;
  double c20_;
public:
  // defualt constructor
  Disjunction(int size,
	      double const * c1, double c10,
	      double const * c2, double c20): size_(size) {
    c1_ = new double[size];
    std::copy (c1, c1+size, c1_);
    c2_ = new double[size];
    std::copy (c2, c2+size, c2_);
    c10_ = c10;
    c20_ = c20;
  }
  // copy constructor
  Disjunction(Disjunction const & other) {
    // save size_
    size_ = other.size();
    // copy c1_
    if (c1_)
      delete[] c1_;
    c1_ = new double[size_];
    double const * other_c1 = other.get_c1();
    std::copy(other_c1, other_c1+size_, c1_);
    // copy c2_
    if (c2_)
      delete[] c2_;
    c2_ = new double[size_];
    double const * other_c2 = other.get_c2();
    std::copy(other_c2, other_c2+size_, c2_);
    // save c10 and c20
    c10_ = other.get_c10();
    c20_ = other.get_c20();
  }
  // copy assignment operator
  Disjunction & operator=(Disjunction const & rhs) {
    // save size_
    size_ = rhs.size();
    // copy c1_
    if (c1_)
      delete[] c1_;
    c1_ = new double[size_];
    double const * rhs_c1 = rhs.get_c1();
    std::copy(rhs_c1, rhs_c1+size_, c1_);
    // copy c2_
    if (c2_)
      delete[] c2_;
    c2_ = new double[size_];
    double const * rhs_c2 = rhs.get_c2();
    std::copy(rhs_c2, rhs_c2+size_, c2_);
    // save c10 and c20
    c10_ = rhs.get_c10();
    c20_ = rhs.get_c20();
    return *this;
  }
  ~Disjunction() { delete[] c1_; delete[] c2_; }
  double const * get_c1() const { return c1_; }
  double get_c10() const { return c10_; }
  double const * get_c2() const { return c2_; }
  double get_c20() const { return c20_; }
  int size() const {return size_;}
};

#endif
<commit_msg>virtual function for generating row cuts from conic interfaces is added.<commit_after>#ifndef CglConicCutGenerator_H
#define CglConicCutGenerator_H

// CGL headers
#include <CglTreeInfo.hpp>
// OsiConic headers
#include <OsiConicSolverInterface.hpp>

// this is an abstract base class for generating conic cuts.
// specific conic cut generators inherit this class.
//
//

// what is common to all conic cut generators?
// for now we assume there is not much in common.
// I will come back here when I implemented all specific cuts
// since I will know then what is common.
// following maybe?
// --cut generating cone
// ----size of cone
// ----members of the cut generating cone
// --disjunction?

class CglConicCutGenerator {
public:
  // default constructor
  CglConicCutGenerator();
  // copy constructor
  CglConicCutGenerator(CglConicCutGenerator const & other);
  // copy assignment operator
  CglConicCutGenerator & operator=(CglConicCutGenerator const & rhs);
  virtual ~CglConicCutGenerator();
  // clone method
  virtual CglConicCutGenerator * clone() const = 0;
  // Create C++ lines so set generator, I do not see why we have this.
  virtual std::string generateCpp( FILE * ) {return "";}

  /// This can be used to refresh any information
  virtual void refreshSolver(OsiConicSolverInterface * si) {}
  // generate cuts
  virtual void generateCuts(const OsiConicSolverInterface & si,
			    OsiConicCuts & cs,
			    const CglTreeInfo info = CglTreeInfo()) = 0;
  // generate linear/ordinary cuts.
  virtual void generateCuts(const OsiConicSolverInterface & si,
			    OsiCuts & cs,
			    const CglTreeInfo info = CglTreeInfo()) = 0;
  int aggressiveness() const;
  void setAggressiveness(int value);
  // set whether can do global cuts
  void setGlobalCuts(bool ability);
  bool canDoGlobalCuts() const;
  /**
     Returns true if may generate cuts in tree (rather than root node).
     Used so know if matrix will change in tree.  Really
     meant so column cut generators can still be active
     without worrying code.
     Default is true
  */
  virtual bool mayGenerateRowCutsInTree() const;
  /// Return true if needs optimal basis to do cuts
  virtual bool needsOptimalBasis() const;
  /// Return maximum length of cut in tree
  virtual int maximumLengthOfCutInTree() const
  { return COIN_INT_MAX;}
private:
  /**
     Aggressiveness - 0 = neutral, 100 is normal root node.
     Really just a hint to cut generator
  */
  int aggressive_;
  /// True if can do global cuts i.e. no general integers
  bool canDoGlobalCuts_;
};

// we define a class to represent a disjunction. This is for conic Cgl
// use only. Not intented for public use.
class Disjunction {
  int size_;
  double * c1_;
  double c10_;
  double * c2_;
  double c20_;
public:
  // defualt constructor
  Disjunction(int size,
	      double const * c1, double c10,
	      double const * c2, double c20): size_(size) {
    c1_ = new double[size];
    std::copy (c1, c1+size, c1_);
    c2_ = new double[size];
    std::copy (c2, c2+size, c2_);
    c10_ = c10;
    c20_ = c20;
  }
  // copy constructor
  Disjunction(Disjunction const & other) {
    // save size_
    size_ = other.size();
    // copy c1_
    if (c1_)
      delete[] c1_;
    c1_ = new double[size_];
    double const * other_c1 = other.get_c1();
    std::copy(other_c1, other_c1+size_, c1_);
    // copy c2_
    if (c2_)
      delete[] c2_;
    c2_ = new double[size_];
    double const * other_c2 = other.get_c2();
    std::copy(other_c2, other_c2+size_, c2_);
    // save c10 and c20
    c10_ = other.get_c10();
    c20_ = other.get_c20();
  }
  // copy assignment operator
  Disjunction & operator=(Disjunction const & rhs) {
    // save size_
    size_ = rhs.size();
    // copy c1_
    if (c1_)
      delete[] c1_;
    c1_ = new double[size_];
    double const * rhs_c1 = rhs.get_c1();
    std::copy(rhs_c1, rhs_c1+size_, c1_);
    // copy c2_
    if (c2_)
      delete[] c2_;
    c2_ = new double[size_];
    double const * rhs_c2 = rhs.get_c2();
    std::copy(rhs_c2, rhs_c2+size_, c2_);
    // save c10 and c20
    c10_ = rhs.get_c10();
    c20_ = rhs.get_c20();
    return *this;
  }
  ~Disjunction() { delete[] c1_; delete[] c2_; }
  double const * get_c1() const { return c1_; }
  double get_c10() const { return c10_; }
  double const * get_c2() const { return c2_; }
  double get_c20() const { return c20_; }
  int size() const {return size_;}
};

#endif
<|endoftext|>


<commit_before>/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "SkFlattenableBuffers.h"
#include "SkLayerRasterizer.h"
#include "SkBlurMaskFilter.h"

static void r0(SkLayerRasterizer* rast, SkPaint& p) {
    p.setMaskFilter(SkBlurMaskFilter::Create(SkIntToScalar(3),
                                             SkBlurMaskFilter::kNormal_BlurStyle))->unref();
    rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));

    p.setMaskFilter(NULL);
    p.setStyle(SkPaint::kStroke_Style);
    p.setStrokeWidth(SK_Scalar1);
    rast->addLayer(p);

    p.setAlpha(0x11);
    p.setStyle(SkPaint::kFill_Style);
    p.setXfermodeMode(SkXfermode::kSrc_Mode);
    rast->addLayer(p);
}

static void r1(SkLayerRasterizer* rast, SkPaint& p) {
    rast->addLayer(p);

    p.setAlpha(0x40);
    p.setXfermodeMode(SkXfermode::kSrc_Mode);
    p.setStyle(SkPaint::kStroke_Style);
    p.setStrokeWidth(SK_Scalar1*2);
    rast->addLayer(p);
}

static void r2(SkLayerRasterizer* rast, SkPaint& p) {
    p.setStyle(SkPaint::kStrokeAndFill_Style);
    p.setStrokeWidth(SK_Scalar1*4);
    rast->addLayer(p);

    p.setStyle(SkPaint::kStroke_Style);
    p.setStrokeWidth(SK_Scalar1*3/2);
    p.setXfermodeMode(SkXfermode::kClear_Mode);
    rast->addLayer(p);
}

static void r3(SkLayerRasterizer* rast, SkPaint& p) {
    p.setStyle(SkPaint::kStroke_Style);
    p.setStrokeWidth(SK_Scalar1*3);
    rast->addLayer(p);

    p.setAlpha(0x20);
    p.setStyle(SkPaint::kFill_Style);
    p.setXfermodeMode(SkXfermode::kSrc_Mode);
    rast->addLayer(p);
}

static void r4(SkLayerRasterizer* rast, SkPaint& p) {
    p.setAlpha(0x60);
    rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));

    p.setAlpha(0xFF);
    p.setXfermodeMode(SkXfermode::kClear_Mode);
    rast->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);

    p.setXfermode(NULL);
    rast->addLayer(p);
}

#include "SkDiscretePathEffect.h"

static void r5(SkLayerRasterizer* rast, SkPaint& p) {
    rast->addLayer(p);

    p.setPathEffect(new SkDiscretePathEffect(SK_Scalar1*4, SK_Scalar1*3))->unref();
    p.setXfermodeMode(SkXfermode::kSrcOut_Mode);
    rast->addLayer(p);
}

static void r6(SkLayerRasterizer* rast, SkPaint& p) {
    rast->addLayer(p);

    p.setAntiAlias(false);
    SkLayerRasterizer* rast2 = new SkLayerRasterizer;
    r5(rast2, p);
    p.setRasterizer(rast2)->unref();
    p.setXfermodeMode(SkXfermode::kClear_Mode);
    rast->addLayer(p);
}

#include "Sk2DPathEffect.h"

static SkPathEffect* MakeDotEffect(SkScalar radius, const SkMatrix& matrix) {
    SkPath path;
    path.addCircle(0, 0, radius);
    return new SkPath2DPathEffect(matrix, path);
}

static void r7(SkLayerRasterizer* rast, SkPaint& p) {
    SkMatrix    lattice;
    lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
    lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
    p.setPathEffect(MakeDotEffect(SK_Scalar1*4, lattice))->unref();
    rast->addLayer(p);
}

static void r8(SkLayerRasterizer* rast, SkPaint& p) {
    rast->addLayer(p);

    SkMatrix    lattice;
    lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
    lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
    p.setPathEffect(MakeDotEffect(SK_Scalar1*2, lattice))->unref();
    p.setXfermodeMode(SkXfermode::kClear_Mode);
    rast->addLayer(p);

    p.setPathEffect(NULL);
    p.setXfermode(NULL);
    p.setStyle(SkPaint::kStroke_Style);
    p.setStrokeWidth(SK_Scalar1);
    rast->addLayer(p);
}

class Line2DPathEffect : public Sk2DPathEffect {
public:
    Line2DPathEffect(SkScalar width, const SkMatrix& matrix)
    : Sk2DPathEffect(matrix), fWidth(width) {}

	virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec) SK_OVERRIDE {
        if (this->INHERITED::filterPath(dst, src, rec)) {
            rec->setStrokeStyle(fWidth);
            return true;
        }
        return false;
    }

    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Line2DPathEffect)

protected:
	virtual void nextSpan(int u, int v, int ucount, SkPath* dst) {
        if (ucount > 1) {
            SkPoint	src[2], dstP[2];

            src[0].set(SkIntToScalar(u) + SK_ScalarHalf,
                       SkIntToScalar(v) + SK_ScalarHalf);
            src[1].set(SkIntToScalar(u+ucount) + SK_ScalarHalf,
                       SkIntToScalar(v) + SK_ScalarHalf);
            this->getMatrix().mapPoints(dstP, src, 2);

            dst->moveTo(dstP[0]);
            dst->lineTo(dstP[1]);
        }
    }

    Line2DPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
        fWidth = buffer.readScalar();
    }
    virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
        this->INHERITED::flatten(buffer);
        buffer.writeScalar(fWidth);
    }

private:
    SkScalar fWidth;

    typedef Sk2DPathEffect INHERITED;
};

static void r9(SkLayerRasterizer* rast, SkPaint& p) {
    rast->addLayer(p);

    SkMatrix    lattice;
    lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
    lattice.postRotate(SkIntToScalar(30), 0, 0);
    p.setPathEffect(new Line2DPathEffect(SK_Scalar1*2, lattice))->unref();
    p.setXfermodeMode(SkXfermode::kClear_Mode);
    rast->addLayer(p);

    p.setPathEffect(NULL);
    p.setXfermode(NULL);
    p.setStyle(SkPaint::kStroke_Style);
    p.setStrokeWidth(SK_Scalar1);
    rast->addLayer(p);
}

typedef void (*raster_proc)(SkLayerRasterizer*, SkPaint&);

static const raster_proc gRastProcs[] = {
    r0, r1, r2, r3, r4, r5, r6, r7, r8, r9
};

static const struct {
    SkColor fMul, fAdd;
} gLightingColors[] = {
    { 0x808080, 0x800000 }, // general case
    { 0x707070, 0x707070 }, // no-pin case
    { 0xFFFFFF, 0x800000 }, // just-add case
    { 0x808080, 0x000000 }, // just-mul case
    { 0xFFFFFF, 0x000000 }  // identity case
};

#include "SkXfermode.h"

static void apply_shader(SkPaint* paint, int index) {
    raster_proc proc = gRastProcs[index];
    if (proc)
    {
        SkPaint p;
        SkLayerRasterizer*  rast = new SkLayerRasterizer;

        p.setAntiAlias(true);
        proc(rast, p);
        paint->setRasterizer(rast)->unref();
    }

#if 0
    SkScalar dir[] = { SK_Scalar1, SK_Scalar1, SK_Scalar1 };
    paint->setMaskFilter(SkBlurMaskFilter::CreateEmboss(dir, SK_Scalar1/4, SkIntToScalar(4), SkIntToScalar(3)))->unref();
#endif
    paint->setColor(SK_ColorBLUE);
}

class TextEffectsGM : public skiagm::GM {
public:
	TextEffectsGM() {}

protected:
    virtual SkString onShortName() SK_OVERRIDE {
        return SkString("texteffects");
    }

    virtual SkISize onISize() SK_OVERRIDE {
        return SkISize::Make(460, 680);
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        canvas->save();

        SkPaint     paint;
        paint.setAntiAlias(true);
        paint.setTextSize(SkIntToScalar(56));

        SkScalar    x = SkIntToScalar(20);
        SkScalar    y = paint.getTextSize();

        SkString str("Hamburgefons");

        for (size_t i = 0; i < SK_ARRAY_COUNT(gRastProcs); i++) {
            apply_shader(&paint, i);

            //  paint.setMaskFilter(NULL);
            //  paint.setColor(SK_ColorBLACK);

            canvas->drawText(str.c_str(), str.size(), x, y, paint);

            y += paint.getFontSpacing();
        }

        canvas->restore();
    }

private:
    typedef skiagm::GM INHERITED;
};

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

static skiagm::GM* MyFactory(void*) { return new TextEffectsGM; }
static skiagm::GMRegistry reg(MyFactory);

<commit_msg>suppress pip for now, since we use locally-defined effects<commit_after>/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "SkFlattenableBuffers.h"
#include "SkLayerRasterizer.h"
#include "SkBlurMaskFilter.h"

static void r0(SkLayerRasterizer* rast, SkPaint& p) {
    p.setMaskFilter(SkBlurMaskFilter::Create(SkIntToScalar(3),
                                             SkBlurMaskFilter::kNormal_BlurStyle))->unref();
    rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));

    p.setMaskFilter(NULL);
    p.setStyle(SkPaint::kStroke_Style);
    p.setStrokeWidth(SK_Scalar1);
    rast->addLayer(p);

    p.setAlpha(0x11);
    p.setStyle(SkPaint::kFill_Style);
    p.setXfermodeMode(SkXfermode::kSrc_Mode);
    rast->addLayer(p);
}

static void r1(SkLayerRasterizer* rast, SkPaint& p) {
    rast->addLayer(p);

    p.setAlpha(0x40);
    p.setXfermodeMode(SkXfermode::kSrc_Mode);
    p.setStyle(SkPaint::kStroke_Style);
    p.setStrokeWidth(SK_Scalar1*2);
    rast->addLayer(p);
}

static void r2(SkLayerRasterizer* rast, SkPaint& p) {
    p.setStyle(SkPaint::kStrokeAndFill_Style);
    p.setStrokeWidth(SK_Scalar1*4);
    rast->addLayer(p);

    p.setStyle(SkPaint::kStroke_Style);
    p.setStrokeWidth(SK_Scalar1*3/2);
    p.setXfermodeMode(SkXfermode::kClear_Mode);
    rast->addLayer(p);
}

static void r3(SkLayerRasterizer* rast, SkPaint& p) {
    p.setStyle(SkPaint::kStroke_Style);
    p.setStrokeWidth(SK_Scalar1*3);
    rast->addLayer(p);

    p.setAlpha(0x20);
    p.setStyle(SkPaint::kFill_Style);
    p.setXfermodeMode(SkXfermode::kSrc_Mode);
    rast->addLayer(p);
}

static void r4(SkLayerRasterizer* rast, SkPaint& p) {
    p.setAlpha(0x60);
    rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));

    p.setAlpha(0xFF);
    p.setXfermodeMode(SkXfermode::kClear_Mode);
    rast->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);

    p.setXfermode(NULL);
    rast->addLayer(p);
}

#include "SkDiscretePathEffect.h"

static void r5(SkLayerRasterizer* rast, SkPaint& p) {
    rast->addLayer(p);

    p.setPathEffect(new SkDiscretePathEffect(SK_Scalar1*4, SK_Scalar1*3))->unref();
    p.setXfermodeMode(SkXfermode::kSrcOut_Mode);
    rast->addLayer(p);
}

static void r6(SkLayerRasterizer* rast, SkPaint& p) {
    rast->addLayer(p);

    p.setAntiAlias(false);
    SkLayerRasterizer* rast2 = new SkLayerRasterizer;
    r5(rast2, p);
    p.setRasterizer(rast2)->unref();
    p.setXfermodeMode(SkXfermode::kClear_Mode);
    rast->addLayer(p);
}

#include "Sk2DPathEffect.h"

static SkPathEffect* MakeDotEffect(SkScalar radius, const SkMatrix& matrix) {
    SkPath path;
    path.addCircle(0, 0, radius);
    return new SkPath2DPathEffect(matrix, path);
}

static void r7(SkLayerRasterizer* rast, SkPaint& p) {
    SkMatrix    lattice;
    lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
    lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
    p.setPathEffect(MakeDotEffect(SK_Scalar1*4, lattice))->unref();
    rast->addLayer(p);
}

static void r8(SkLayerRasterizer* rast, SkPaint& p) {
    rast->addLayer(p);

    SkMatrix    lattice;
    lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
    lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
    p.setPathEffect(MakeDotEffect(SK_Scalar1*2, lattice))->unref();
    p.setXfermodeMode(SkXfermode::kClear_Mode);
    rast->addLayer(p);

    p.setPathEffect(NULL);
    p.setXfermode(NULL);
    p.setStyle(SkPaint::kStroke_Style);
    p.setStrokeWidth(SK_Scalar1);
    rast->addLayer(p);
}

class Line2DPathEffect : public Sk2DPathEffect {
public:
    Line2DPathEffect(SkScalar width, const SkMatrix& matrix)
    : Sk2DPathEffect(matrix), fWidth(width) {}

	virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec) SK_OVERRIDE {
        if (this->INHERITED::filterPath(dst, src, rec)) {
            rec->setStrokeStyle(fWidth);
            return true;
        }
        return false;
    }

    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Line2DPathEffect)

protected:
	virtual void nextSpan(int u, int v, int ucount, SkPath* dst) {
        if (ucount > 1) {
            SkPoint	src[2], dstP[2];

            src[0].set(SkIntToScalar(u) + SK_ScalarHalf,
                       SkIntToScalar(v) + SK_ScalarHalf);
            src[1].set(SkIntToScalar(u+ucount) + SK_ScalarHalf,
                       SkIntToScalar(v) + SK_ScalarHalf);
            this->getMatrix().mapPoints(dstP, src, 2);

            dst->moveTo(dstP[0]);
            dst->lineTo(dstP[1]);
        }
    }

    Line2DPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
        fWidth = buffer.readScalar();
    }
    virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
        this->INHERITED::flatten(buffer);
        buffer.writeScalar(fWidth);
    }

private:
    SkScalar fWidth;

    typedef Sk2DPathEffect INHERITED;
};

static void r9(SkLayerRasterizer* rast, SkPaint& p) {
    rast->addLayer(p);

    SkMatrix    lattice;
    lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
    lattice.postRotate(SkIntToScalar(30), 0, 0);
    p.setPathEffect(new Line2DPathEffect(SK_Scalar1*2, lattice))->unref();
    p.setXfermodeMode(SkXfermode::kClear_Mode);
    rast->addLayer(p);

    p.setPathEffect(NULL);
    p.setXfermode(NULL);
    p.setStyle(SkPaint::kStroke_Style);
    p.setStrokeWidth(SK_Scalar1);
    rast->addLayer(p);
}

typedef void (*raster_proc)(SkLayerRasterizer*, SkPaint&);

static const raster_proc gRastProcs[] = {
    r0, r1, r2, r3, r4, r5, r6, r7, r8, r9
};

static const struct {
    SkColor fMul, fAdd;
} gLightingColors[] = {
    { 0x808080, 0x800000 }, // general case
    { 0x707070, 0x707070 }, // no-pin case
    { 0xFFFFFF, 0x800000 }, // just-add case
    { 0x808080, 0x000000 }, // just-mul case
    { 0xFFFFFF, 0x000000 }  // identity case
};

#include "SkXfermode.h"

static void apply_shader(SkPaint* paint, int index) {
    raster_proc proc = gRastProcs[index];
    if (proc)
    {
        SkPaint p;
        SkLayerRasterizer*  rast = new SkLayerRasterizer;

        p.setAntiAlias(true);
        proc(rast, p);
        paint->setRasterizer(rast)->unref();
    }

#if 0
    SkScalar dir[] = { SK_Scalar1, SK_Scalar1, SK_Scalar1 };
    paint->setMaskFilter(SkBlurMaskFilter::CreateEmboss(dir, SK_Scalar1/4, SkIntToScalar(4), SkIntToScalar(3)))->unref();
#endif
    paint->setColor(SK_ColorBLUE);
}

class TextEffectsGM : public skiagm::GM {
public:
	TextEffectsGM() {}

protected:
    virtual SkString onShortName() SK_OVERRIDE {
        return SkString("texteffects");
    }

    virtual SkISize onISize() SK_OVERRIDE {
        return SkISize::Make(460, 680);
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        canvas->save();

        SkPaint     paint;
        paint.setAntiAlias(true);
        paint.setTextSize(SkIntToScalar(56));

        SkScalar    x = SkIntToScalar(20);
        SkScalar    y = paint.getTextSize();

        SkString str("Hamburgefons");

        for (size_t i = 0; i < SK_ARRAY_COUNT(gRastProcs); i++) {
            apply_shader(&paint, i);

            //  paint.setMaskFilter(NULL);
            //  paint.setColor(SK_ColorBLACK);

            canvas->drawText(str.c_str(), str.size(), x, y, paint);

            y += paint.getFontSpacing();
        }

        canvas->restore();
    }

    virtual uint32_t onGetFlags() const SK_OVERRIDE {
        // want to skip serialization due to custom effects only defined here
        return kSkipPipe_Flag;
    }

private:
    typedef skiagm::GM INHERITED;
};

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

static skiagm::GM* MyFactory(void*) { return new TextEffectsGM; }
static skiagm::GMRegistry reg(MyFactory);

<|endoftext|>


<commit_before><commit_msg>17951<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2011 Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 */

#include "swmodel.h"

#include <QDebug>

#include <QDateTime>
#include <QStringList>
#include <QDesktopServices>

#include <libsocialweb-qt/swclientservice.h>
#include <libsocialweb-qt/swclientitemview.h>
#include <libsocialweb-qt/swclientitem.h>

#include <actions.h>

SwModel::SwModel(SwClientService *clientService, QObject *parent):
    McaFeedModel(parent),
    mService(clientService),
    mView(0)

{
    openView();
}
/*
// Developers: Please see annotations in emailmodel.cpp for help on how to
//   implement your own feed model. This one is no different.
SocialModel::SocialModel(QObject *parent): McaFeedModel(parent)
{
    m_size = 15;
    m_socials = new Social[m_size];

    // ensure Socials generated are always the same
    qsrand(0);

    QDateTime date = QDateTime::currentDateTime();
    for (int i=0; i<m_size; i++) {
        date = date.addSecs(-qrand() % 10000);
        m_socials[i].timestamp = date;

        // use consistent uuids for testing
        m_socials[i].uuid = QString::number(20000 + i);

        QStringList list;
        list << "New friend" << "Sarah is listening" <<
                "Photo album uploaded" << "John likes MeeGo";
        int msg = qrand() % list.size();
        m_socials[i].subject = list.at(msg);

        list.clear();
        list << "Alex has accepted your friend request"
                <<
                "Sarah is listening to Beethoven's 5th Symphony"
                <<
                "Photos from the last week of my road trip to Paris"
                <<
                "Hey guys, check out these cool new MeeGo applications";
        m_socials[i].body = list.at(msg);

        connect(&m_socials[i].actions, SIGNAL(standardAction(QString,QString)),
                this, SLOT(performAction(QString,QString)));
    }
}

SocialModel::~SocialModel()
{
    delete [] m_socials;
}
*/

int SwModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return mItems.count();
}

QVariant SwModel::data(const QModelIndex &index, int role) const
{
    int row = index.row();
    if ((row >= mItems.count()) || (row < 0))
        return QVariant();
//    qDebug() << QString("mItems.count(): ") << mItems.count();
/*
    switch (role) {
    case RequiredTypeRole:
        return QString("content");

    case RequiredUniqueIdRole:
        return m_socials[row].uuid;

    case RequiredTimestampRole:
        return m_socials[row].timestamp;

    case GenericTitleRole:
        return m_socials[row].subject;

    case GenericContentRole:
        return m_socials[row].body;

    case GenericAvatarUrlRole:
        if (index.row() % 2)
            return QString("file://tmp/happy.svg");
        else
            return QString("file://tmp/wink.svg");

    case CommonActionsRole:
        return QVariant::fromValue<McaActions*>(&m_socials[row].actions);

    default:
        return QVariant();
    };
    */
 //   qDebug() << QString("row: %1, mItems.count(): %2").arg(QString::number(row), QString::number(mItems.count()));
//    qDebug() << QString("mItems.at(row): %1/%2").arg(QString::number((int)(mItems.at(row).item)), QString::number((int)(mItems.at(row).action))) ;
    SwItem item = mItems.at(row);
    SwClientItem *swItem = item.item;
    if (!swItem)
        return QVariant();

    switch (role) {
    case RequiredTypeRole:
        {
/*            QString itemType;

            switch (swItem->getItemType()) {
            case SwClientItem::ItemTypeText:
                itemType = "text";
                break;
            case SwClientItem::ItemTypePic:
                itemType = "picture";
                break;
            case SwClientItem::ItemTypeLast:
            default:
                itemType = "unknown";
                qDebug() << QString("Got unknown item type for SwClientItem of service %1! Props:").arg(swItem->getServiceName());
                qDebug() << swItem->getSwItemProps();
                break;
            }

            return QVariant::fromValue<QString>(QString("%1/%2").arg(itemType, swItem->getServiceName()));*/
            return "content";
            break;
        }

    case RequiredUniqueIdRole:
        {
            return QVariant::fromValue<QString>(swItem->getID());
            break;
        }

    case RequiredTimestampRole:
        {
            return QVariant::fromValue<QDateTime>(swItem->getDateTime());
            break;
        }

    case CommonUuidRole:
        {
            return QVariant::fromValue<QString>(swItem->getSwUUID());
            break;
        }

    case GenericTitleRole:
        {
            return QVariant::fromValue<QString>(swItem->getAuthorName());
            break;
        }

//    case GenericIconUrlRole:
//        {
//            //TODO: Ugly - need to resolve this in libsocialweb-qt -
//            //getService gives us a const SwClientService, but the
//            //SwClientService::getServiceConfig is not const, as it will
//            //instanciate a SwClientServiceConfig private member object if
//            //it's not already instanciated...
//            SwClientService *swService = const_cast<SwClientService *>(swItem->getService());

//            QString path = swService->getServiceConfig()->getIconPath();
//            if (path.isEmpty())
//                return QVariant();
//            return QVariant::fromValue<QString>(QString("file://%1").arg(path));
//            break;
//        }

    case GenericRelevanceRole:
        {
            return QVariant::fromValue<qreal>(1.0);
            break;
        }

    case GenericPictureUrlRole:
        {
            QString path = swItem->getThumbnailPath();
            if (path.isEmpty())
                return QVariant();
            return QVariant::fromValue<QString>(QString("file://%1").arg(path));
            break;
        }
    case GenericAvatarUrlRole:
        {
            QString path = swItem->getAuthorIconPath();
            if (path.isEmpty())
                return QVariant();
            return QVariant::fromValue<QString>(QString("file://%1").arg(path));
            break;
        }
    case GenericContentRole:
        {
            //Note that getContent will return the message text for
            //ItemTypeText, and will appropriately fall back to the
            //picture title on ItemTypePic
            return QVariant::fromValue<QString>(swItem->getContent());
        }

    case CommonActionsRole:
        return QVariant::fromValue<McaActions*>(item.action);

    default:
        return QVariant();
    }

    return QVariant();

}

void SwModel::performAction(QString action, QString uniqueid)
{
    qDebug() << "Action" << action << "called for libsocialweb item" << uniqueid;
    //Right now, assume only default action.
    foreach (struct SwItem item, mItems) {
        if (item.item->getID() == uniqueid) {
            QDesktopServices::openUrl(item.item->getURL());
            break;
        }

    }

}

//Private slots:

void SwModel::onItemsAdded(QList<SwClientItem *> items)
{
    foreach (SwClientItem *swItem, items) {
        struct SwItem item;
        item.item = swItem;
        item.action = new McaActions();
        connect(item.action,
                SIGNAL(standardAction(QString,QString)),
                this,
                SLOT(performAction(QString,QString)));
        this->beginInsertRows(QModelIndex(), mItems.count(), mItems.count());
        mItems.append(item);
        this->endInsertRows();
    }
}

void SwModel::onItemsChanged(QList<SwClientItem *> items)
{
    int i;
    //TODO - see if there's a better way than an inner and outer loop...
    foreach (SwClientItem *swItem, items) {
        for (i = 0; i < mItems.count(); ++i) {
            if (swItem->getID() == mItems.at(i).item->getID()) {
                struct SwItem item;
                item.action = mItems.at(i).action;
                item.item = swItem;
                QModelIndex qmi = this->createIndex(i, 0, 0);
                mItems.replace(i, item);
                emit this->dataChanged(qmi, qmi);
                break;
            }
        }
    }
}

void SwModel::onItemsRemoved(ArrayOfSwItemId items)
{
    int i;
    foreach (SwItemId itemID, items) {
        for (i = 0; i < mItems.count(); ++i) {
            struct SwItem item = mItems.at(i);
            if (itemID.uuid == item.item->getSwUUID()) {
                this->beginRemoveRows(QModelIndex(), i, i);
                mItems.removeAt(i);
                this->endInsertRows();
                break;
            }
        }
    }
}

//Private functions:

void SwModel::openView()
{
    //If we had a view open previously and gotten items, this will
    //ensure we don't get duplicate items from the new view...
    this->beginRemoveRows(QModelIndex(), 0, mItems.count());
    mItems.clear();
    this->endRemoveRows();

    mView = mService->openView("feed");
    connect(mView,
            SIGNAL(ItemsAdded(QList<SwClientItem*>)),
            this,
            SLOT(onItemsAdded(QList<SwClientItem*>)));
    connect(mView,
            SIGNAL(ItemsChanged(QList<SwClientItem*>)),
            this,
            SLOT(onItemsChanged(QList<SwClientItem*>)));
    connect(mView,
            SIGNAL(ItemsRemoved(ArrayOfSwItemId)),
            this,
            SLOT(onItemsRemoved(ArrayOfSwItemId)));
    mView->startView();
}

void SwModel::closeView()
{
    mView->stopView();
    mView->closeView();
    delete mView;
    mView = 0;
}
<commit_msg>Fix BMC#17897 - Make action handling actually pay attention to what action is being called.<commit_after>/*
 * Copyright 2011 Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 */

#include "swmodel.h"

#include <QDebug>

#include <QDateTime>
#include <QStringList>
#include <QDesktopServices>

#include <libsocialweb-qt/swclientservice.h>
#include <libsocialweb-qt/swclientitemview.h>
#include <libsocialweb-qt/swclientitem.h>

#include <actions.h>

SwModel::SwModel(SwClientService *clientService, QObject *parent):
    McaFeedModel(parent),
    mService(clientService),
    mView(0)

{
    openView();
}
/*
// Developers: Please see annotations in emailmodel.cpp for help on how to
//   implement your own feed model. This one is no different.
SocialModel::SocialModel(QObject *parent): McaFeedModel(parent)
{
    m_size = 15;
    m_socials = new Social[m_size];

    // ensure Socials generated are always the same
    qsrand(0);

    QDateTime date = QDateTime::currentDateTime();
    for (int i=0; i<m_size; i++) {
        date = date.addSecs(-qrand() % 10000);
        m_socials[i].timestamp = date;

        // use consistent uuids for testing
        m_socials[i].uuid = QString::number(20000 + i);

        QStringList list;
        list << "New friend" << "Sarah is listening" <<
                "Photo album uploaded" << "John likes MeeGo";
        int msg = qrand() % list.size();
        m_socials[i].subject = list.at(msg);

        list.clear();
        list << "Alex has accepted your friend request"
                <<
                "Sarah is listening to Beethoven's 5th Symphony"
                <<
                "Photos from the last week of my road trip to Paris"
                <<
                "Hey guys, check out these cool new MeeGo applications";
        m_socials[i].body = list.at(msg);

        connect(&m_socials[i].actions, SIGNAL(standardAction(QString,QString)),
                this, SLOT(performAction(QString,QString)));
    }
}

SocialModel::~SocialModel()
{
    delete [] m_socials;
}
*/

int SwModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return mItems.count();
}

QVariant SwModel::data(const QModelIndex &index, int role) const
{
    int row = index.row();
    if ((row >= mItems.count()) || (row < 0))
        return QVariant();
//    qDebug() << QString("mItems.count(): ") << mItems.count();
/*
    switch (role) {
    case RequiredTypeRole:
        return QString("content");

    case RequiredUniqueIdRole:
        return m_socials[row].uuid;

    case RequiredTimestampRole:
        return m_socials[row].timestamp;

    case GenericTitleRole:
        return m_socials[row].subject;

    case GenericContentRole:
        return m_socials[row].body;

    case GenericAvatarUrlRole:
        if (index.row() % 2)
            return QString("file://tmp/happy.svg");
        else
            return QString("file://tmp/wink.svg");

    case CommonActionsRole:
        return QVariant::fromValue<McaActions*>(&m_socials[row].actions);

    default:
        return QVariant();
    };
    */
 //   qDebug() << QString("row: %1, mItems.count(): %2").arg(QString::number(row), QString::number(mItems.count()));
//    qDebug() << QString("mItems.at(row): %1/%2").arg(QString::number((int)(mItems.at(row).item)), QString::number((int)(mItems.at(row).action))) ;
    SwItem item = mItems.at(row);
    SwClientItem *swItem = item.item;
    if (!swItem)
        return QVariant();

    switch (role) {
    case RequiredTypeRole:
        {
/*            QString itemType;

            switch (swItem->getItemType()) {
            case SwClientItem::ItemTypeText:
                itemType = "text";
                break;
            case SwClientItem::ItemTypePic:
                itemType = "picture";
                break;
            case SwClientItem::ItemTypeLast:
            default:
                itemType = "unknown";
                qDebug() << QString("Got unknown item type for SwClientItem of service %1! Props:").arg(swItem->getServiceName());
                qDebug() << swItem->getSwItemProps();
                break;
            }

            return QVariant::fromValue<QString>(QString("%1/%2").arg(itemType, swItem->getServiceName()));*/
            return "content";
            break;
        }

    case RequiredUniqueIdRole:
        {
            return QVariant::fromValue<QString>(swItem->getID());
            break;
        }

    case RequiredTimestampRole:
        {
            return QVariant::fromValue<QDateTime>(swItem->getDateTime());
            break;
        }

    case CommonUuidRole:
        {
            return QVariant::fromValue<QString>(swItem->getSwUUID());
            break;
        }

    case GenericTitleRole:
        {
            return QVariant::fromValue<QString>(swItem->getAuthorName());
            break;
        }

//    case GenericIconUrlRole:
//        {
//            //TODO: Ugly - need to resolve this in libsocialweb-qt -
//            //getService gives us a const SwClientService, but the
//            //SwClientService::getServiceConfig is not const, as it will
//            //instanciate a SwClientServiceConfig private member object if
//            //it's not already instanciated...
//            SwClientService *swService = const_cast<SwClientService *>(swItem->getService());

//            QString path = swService->getServiceConfig()->getIconPath();
//            if (path.isEmpty())
//                return QVariant();
//            return QVariant::fromValue<QString>(QString("file://%1").arg(path));
//            break;
//        }

    case GenericRelevanceRole:
        {
            return QVariant::fromValue<qreal>(1.0);
            break;
        }

    case GenericPictureUrlRole:
        {
            QString path = swItem->getThumbnailPath();
            if (path.isEmpty())
                return QVariant();
            return QVariant::fromValue<QString>(QString("file://%1").arg(path));
            break;
        }
    case GenericAvatarUrlRole:
        {
            QString path = swItem->getAuthorIconPath();
            if (path.isEmpty())
                return QVariant();
            return QVariant::fromValue<QString>(QString("file://%1").arg(path));
            break;
        }
    case GenericContentRole:
        {
            //Note that getContent will return the message text for
            //ItemTypeText, and will appropriately fall back to the
            //picture title on ItemTypePic
            return QVariant::fromValue<QString>(swItem->getContent());
        }

    case CommonActionsRole:
        return QVariant::fromValue<McaActions*>(item.action);

    default:
        return QVariant();
    }

    return QVariant();

}

void SwModel::performAction(QString action, QString uniqueid)
{
    qDebug() << "Action" << action << "called for libsocialweb item" << uniqueid;
    //Right now, assume only default action.
    foreach (struct SwItem item, mItems) {
        if (item.item->getID() == uniqueid) {
            if (action == "default")
                QDesktopServices::openUrl(item.item->getURL());
            else
                qDebug() << "Unrecognized action" << action << "called!";
            break;
        }

    }

}

//Private slots:

void SwModel::onItemsAdded(QList<SwClientItem *> items)
{
    foreach (SwClientItem *swItem, items) {
        struct SwItem item;
        item.item = swItem;
        item.action = new McaActions();
        connect(item.action,
                SIGNAL(standardAction(QString,QString)),
                this,
                SLOT(performAction(QString,QString)));
        this->beginInsertRows(QModelIndex(), mItems.count(), mItems.count());
        mItems.append(item);
        this->endInsertRows();
    }
}

void SwModel::onItemsChanged(QList<SwClientItem *> items)
{
    int i;
    //TODO - see if there's a better way than an inner and outer loop...
    foreach (SwClientItem *swItem, items) {
        for (i = 0; i < mItems.count(); ++i) {
            if (swItem->getID() == mItems.at(i).item->getID()) {
                struct SwItem item;
                item.action = mItems.at(i).action;
                item.item = swItem;
                QModelIndex qmi = this->createIndex(i, 0, 0);
                mItems.replace(i, item);
                emit this->dataChanged(qmi, qmi);
                break;
            }
        }
    }
}

void SwModel::onItemsRemoved(ArrayOfSwItemId items)
{
    int i;
    foreach (SwItemId itemID, items) {
        for (i = 0; i < mItems.count(); ++i) {
            struct SwItem item = mItems.at(i);
            if (itemID.uuid == item.item->getSwUUID()) {
                this->beginRemoveRows(QModelIndex(), i, i);
                mItems.removeAt(i);
                this->endInsertRows();
                break;
            }
        }
    }
}

//Private functions:

void SwModel::openView()
{
    //If we had a view open previously and gotten items, this will
    //ensure we don't get duplicate items from the new view...
    this->beginRemoveRows(QModelIndex(), 0, mItems.count());
    mItems.clear();
    this->endRemoveRows();

    mView = mService->openView("feed");
    connect(mView,
            SIGNAL(ItemsAdded(QList<SwClientItem*>)),
            this,
            SLOT(onItemsAdded(QList<SwClientItem*>)));
    connect(mView,
            SIGNAL(ItemsChanged(QList<SwClientItem*>)),
            this,
            SLOT(onItemsChanged(QList<SwClientItem*>)));
    connect(mView,
            SIGNAL(ItemsRemoved(ArrayOfSwItemId)),
            this,
            SLOT(onItemsRemoved(ArrayOfSwItemId)));
    mView->startView();
}

void SwModel::closeView()
{
    mView->stopView();
    mView->closeView();
    delete mView;
    mView = 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2013-2016 Christian Lockley
 *
 * 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.
 */
#define _DEFAULT_SOURCE
#include <libgen.h>
#include "watchdogd.hpp"
#include "sub.hpp"
#include <dirent.h>
#include <semaphore.h>
#include "testdir.hpp"
#include "exe.hpp"
#include "repair.hpp"
#include <sys/eventfd.h>
#include "threadpool.hpp"
#include "futex.hpp"

static std::atomic_int sem = {0};
//The dirent_buf_size function was written by Ben Hutchings and released under the following license.

//Permission is hereby granted, free of charge, to any person obtaining a copy of this
//software and associated documentation files (the "Software"), to deal in the Software
//without restriction, including without limitation the rights to use, copy, modify, merge,
//publish, distribute, sublicense, and/or sell copies of the Software, and to permit
//persons to whom the Software is furnished to do so, subject to the following
//condition:
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
//MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
//DEALINGS IN THE SOFTWARE.

//Copied into this program Sun September 8, 2013 by Christian Lockley

size_t DirentBufSize(DIR * dirp)
{
	long name_max;
	size_t name_end;
#if defined(HAVE_FPATHCONF) && defined(HAVE_DIRFD) \
&& defined(_PC_NAME_MAX)
	name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
	if (name_max == -1)
#if defined(NAME_MAX)
		name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
#else
		return (size_t) (-1);
#endif
#else
#if defined(NAME_MAX)
	name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
#else
#error "buffer size for readdir_r cannot be determined"
#endif
#endif
	name_end =
	    (size_t) offsetof(struct dirent,
			      d_name) + (unsigned long)name_max + 1;
	return (name_end > sizeof(struct dirent)
		? name_end : sizeof(struct dirent));
}

static void DeleteDuplicates(ProcessList * p)
{
	assert(p != NULL);

	repaircmd_t *c = NULL;
	repaircmd_t *next = NULL;

	list_for_each_entry(c, next, &p->head, entry) {
		repaircmd_t *b = NULL;
		repaircmd_t *next2 = NULL;
		if (c->legacy) {
			list_for_each_entry(b, next2, &p->head, entry) {
				if (!b->legacy) {
					if (strcmp(c->path, b->path) == 0) {
						list_del(&c->entry);
						free((void *)c->path);
						free((void *)c);
						Logmsg(LOG_INFO, "Using configuration info for %s script", b->path);
					}
				}
			}
		}
	}
}

int CreateLinkedListOfExes(char *repairScriptFolder, ProcessList * p,
			   struct cfgoptions *const config)
{
	assert(p != NULL);
	assert(repairScriptFolder != NULL);

	struct stat buffer;
	struct dirent *ent = NULL;

	list_init(&p->head);

	int fd = open(repairScriptFolder, O_DIRECTORY | O_RDONLY);

	if (fd == -1) {
		if (!(IDENTIFY & config->options)) {
			fprintf(stderr, "watchdogd: %s: %s\n", repairScriptFolder,
				MyStrerror(errno));
		}

		if (config->options & FORCE || config->options & SOFTBOOT || config->haveConfigFile == false) {
			return 0;
		}

		return 1;
	}

	DIR *dir = fdopendir(fd);

	if (dir == NULL) {
		Logmsg(LOG_ERR, "watchdogd: %s", MyStrerror(errno));
		close(fd);
		return -1;
	}

	errno = 0;

	while ((ent = readdir(dir)) != NULL) {

		int statfd = dirfd(dir);

		if (statfd == -1) {
			goto error;
		}

		if (strchr(".", ent->d_name[0]) != NULL && !(config->options & FORCE)) {
			continue;
		}

		if (fstatat(statfd, ent->d_name, &buffer, 0) < 0)
			continue;

		if (IsRepairScriptConfig(ent->d_name) == 0) {
			if (S_ISREG(buffer.st_mode) == 0) {
				continue;
			}

			if (!(buffer.st_mode & S_IXUSR))
				continue;

			if (!(buffer.st_mode & S_IRUSR))
				continue;
		} else {
			if (S_ISREG(buffer.st_mode) == 0) {
				continue;
			}
		}

		repaircmd_t *cmd = (repaircmd_t *) calloc(1, sizeof(*cmd));

		if (cmd == NULL) {
			goto error;
		}

		for (size_t i = 0; i < strlen(repairScriptFolder); i += 1) {
			if (repairScriptFolder[i] == '/' && i < strlen(repairScriptFolder)
			    && repairScriptFolder[i+1] == '\0') {
				repairScriptFolder[i] = '\0';
			}
		}

		Wasprintf((char **)&cmd->path, "%s/%s", repairScriptFolder, ent->d_name);

		if (cmd->path == NULL) {
			assert(cmd != NULL);
			free(cmd);
			goto error;
		}

		if (IsRepairScriptConfig(ent->d_name) == 0) {
			cmd->legacy = true;
		} else {
			//For V3 repair scripts cmd->path refers to the pathname of the repair script config file
			if (LoadRepairScriptLink
			    (&cmd->spawnattr, (char *)cmd->path) == false) {
				free((void *)cmd->path);
				free(cmd);
				continue;
			}

			cmd->spawnattr.repairFilePathname = strdup(cmd->path);
			free((void *)cmd->path);
			cmd->path = NULL;
			cmd->path = cmd->spawnattr.execStart;

			char * rel = basename(strdup(cmd->path));

			if (strcmp(rel, cmd->path) == 0) {
				free((void*)rel);
				Wasprintf((char **)&rel, "%s/%s", repairScriptFolder, cmd->path);
				free((void*)cmd->path);
				cmd->path = cmd->spawnattr.execStart = rel;
			}

			if (cmd->path == NULL) {
				fprintf(stderr,
					"Ignoring malformed repair file: %s\n",
					ent->d_name);
				free(cmd);
				continue;
			}

			if (fd < 0) {
				fprintf(stderr, "unable to open file %s:\n",
					MyStrerror(errno));
				free((void *)cmd->path);
				free((void *)cmd);
				continue;
			}

			if (IsExe(cmd->path, false) < 0) {
				fprintf(stderr, "%s is not an executable\n",
					cmd->path);
				free((void *)cmd->path);
				free((void *)cmd);
				continue;
			}

			cmd->legacy = false;
		}

		list_add(&cmd->entry, &p->head);
	}

	assert(fd != -1);

	close(fd);
	closedir(dir);
	DeleteDuplicates(p);
	return 0;

 error:
	assert(fd != -1);
	close(fd);
	Logmsg(LOG_ERR, "watchdogd: %s", MyStrerror(errno));
	closedir(dir);

	return -1;
}

void FreeExeList(ProcessList * p)
{
	assert(p != NULL);

	repaircmd_t *c = NULL;
	repaircmd_t *next = NULL;

	list_for_each_entry(c, next, &p->head, entry) {
		list_del(&c->entry);
		free((void *)c->path);
		if (c->legacy == false) {
			free((void *)c->spawnattr.user);
			free((void *)c->spawnattr.group);
			free((void *)c->spawnattr.workingDirectory);
			free((void *)c->spawnattr.repairFilePathname);
			free((void *)c->spawnattr.noNewPrivileges);
		}
		free(c);
	}
}

static void * __ExecScriptWorkerThread(void *a)
{
	assert(a != NULL);

	__sync_synchronize();

	Container *container = (Container *) a;
	repaircmd_t *c = container->cmd;
	container->workerThreadCount += 1;
	sem = 1;
	FutexWake(&sem);
	__sync_synchronize();

	if (c->legacy == false) {
		if (c->retString[0] == '\0') {
			c->ret =
			    SpawnAttr(&c->spawnattr, c->path, c->path, c->mode == TEST ? "test": "repair",
				      NULL);
		} else {
			c->ret =
			    SpawnAttr(&c->spawnattr, c->path, c->path, c->mode == TEST ? "test": "repair", c->retString,
				      NULL);
		}
	} else {
		spawnattr_t attr = {
				.workingDirectory = NULL, .repairFilePathname = NULL,
	        		.execStart = NULL, .user = NULL, .group = NULL,
				.timeout = container->config->repairBinTimeout, .nice = 0, .umask = 0,
				.noNewPrivileges = false, .hasUmask = false
		};

		if (c->retString[0] == '\0') {
			if (c->mode == TEST) {
				c->ret = SpawnAttr(&attr, c->path, c->path, "test", NULL);
			} else {
				c->ret = SpawnAttr(&attr, c->path, c->path, "repair", c->path, NULL);
			}
		} else {
			if (c->mode == TEST) {
				c->ret = SpawnAttr(&attr, c->path, c->path, "test", NULL);
			} else {
				c->ret = SpawnAttr(&attr, c->path, c->path, "repair", c->retString, c->path, NULL);
			}
		}
	}

	c->retString[0] = '\0';

	container->workerThreadCount -= 1;

	__sync_synchronize();
	return NULL;
}

static void __WaitForWorkers(Container const *container)
{
	while (container->workerThreadCount != 0) {
		sleep(1);
	}
}

static int __ExecuteRepairScripts(void *a)
{
	struct executeScriptsStruct *arg = (struct executeScriptsStruct *)a;
	ProcessList *p = arg->list;
	struct cfgoptions *s = arg->config;

	Container container = {{0}, s, NULL};

	repaircmd_t *c = NULL;
	repaircmd_t *next = NULL;

	list_for_each_entry(c, next, &p->head, entry) {
		container.cmd = c;
		container.cmd->mode = TEST;

		c->retString[0] = '\0';
		ThreadPoolAddTask(__ExecScriptWorkerThread, &container, true);
		__sync_synchronize();
		FutexWait(&sem, 0);
		sem = 0;
	}

	c = NULL;
	next = NULL;

	__WaitForWorkers(&container);

	list_for_each_entry(c, next, &p->head, entry) {
		if (c->ret == 0) {
			continue;
		}

		container.cmd = c;
		portable_snprintf(container.cmd->retString, sizeof(container.cmd->retString), "%i", c->ret);

		container.cmd->mode = REPAIR;

		ThreadPoolAddTask(__ExecScriptWorkerThread, &container, true);
		__sync_synchronize();
		FutexWait(&sem, 0);
		sem = 0;
	}

	__WaitForWorkers(&container);

	c = NULL;
	next = NULL;

	list_for_each_entry(c, next, &p->head, entry) {
		if (c->ret != 0) {
			Logmsg(LOG_ERR, "repair %s script failed",
				c->legacy == false ? c->spawnattr.repairFilePathname : c->path);
			return 1;
		}
	}

	return 0;
}

static int pipeFd[2] = {0};

bool ExecuteRepairScriptsPreFork(ProcessList * p, struct cfgoptions *s)
{
	if (list_is_empty(&p->head)) {
		return true;
	}

	pipe(pipeFd);

	pid_t pid = fork();

	if (pid == -1) {
		Logmsg(LOG_ERR, "%s\n", MyStrerror(errno));
		return false;
	} else if (pid == 0) {
		close(pipeFd[0]);
		pid_t pid = fork();

#if defined(__linux__)
		if (LinuxRunningSystemd() == 1) {
			unsetenv("NOTIFY_SOCKET");
		}
#endif

		unsetenv("LD_PRELOAD");

		if (pid > 0) {
			_Exit(0);
		}

		if (pid < 0) {
			Logmsg(LOG_ERR, "fork failed: %s", MyStrerror(errno));
			abort();
		}

		char b[1];

		ThreadPoolNew();

		while (true) {
			uint64_t value = 0;
			struct executeScriptsStruct ess;
			ess.list = p;
			ess.config = s;

			int ret = __ExecuteRepairScripts(&ess);

			write(pipeFd[1], &ret, sizeof(ret));
		}

		exit(0);
	}
	close(pipeFd[1]);
	return true;
}

int ExecuteRepairScripts(void)
{
	uint64_t value = 1;
	int ret = 0;

	read(pipeFd[0], &ret, sizeof(ret));

	if (ret != 0) {
		return -1;
	}

	return 0;
}
<commit_msg>delete readdir_r buffer sizing code<commit_after>/*
 * Copyright 2013-2016 Christian Lockley
 *
 * 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.
 */
#define _DEFAULT_SOURCE
#include <libgen.h>
#include "watchdogd.hpp"
#include "sub.hpp"
#include <dirent.h>
#include <semaphore.h>
#include "testdir.hpp"
#include "exe.hpp"
#include "repair.hpp"
#include <sys/eventfd.h>
#include "threadpool.hpp"
#include "futex.hpp"

static std::atomic_int sem = {0};

static void DeleteDuplicates(ProcessList * p)
{
	assert(p != NULL);

	repaircmd_t *c = NULL;
	repaircmd_t *next = NULL;

	list_for_each_entry(c, next, &p->head, entry) {
		repaircmd_t *b = NULL;
		repaircmd_t *next2 = NULL;
		if (c->legacy) {
			list_for_each_entry(b, next2, &p->head, entry) {
				if (!b->legacy) {
					if (strcmp(c->path, b->path) == 0) {
						list_del(&c->entry);
						free((void *)c->path);
						free((void *)c);
						Logmsg(LOG_INFO, "Using configuration info for %s script", b->path);
					}
				}
			}
		}
	}
}

int CreateLinkedListOfExes(char *repairScriptFolder, ProcessList * p,
			   struct cfgoptions *const config)
{
	assert(p != NULL);
	assert(repairScriptFolder != NULL);

	struct stat buffer;
	struct dirent *ent = NULL;

	list_init(&p->head);

	int fd = open(repairScriptFolder, O_DIRECTORY | O_RDONLY);

	if (fd == -1) {
		if (!(IDENTIFY & config->options)) {
			fprintf(stderr, "watchdogd: %s: %s\n", repairScriptFolder,
				MyStrerror(errno));
		}

		if (config->options & FORCE || config->options & SOFTBOOT || config->haveConfigFile == false) {
			return 0;
		}

		return 1;
	}

	DIR *dir = fdopendir(fd);

	if (dir == NULL) {
		Logmsg(LOG_ERR, "watchdogd: %s", MyStrerror(errno));
		close(fd);
		return -1;
	}

	errno = 0;

	while ((ent = readdir(dir)) != NULL) {

		int statfd = dirfd(dir);

		if (statfd == -1) {
			goto error;
		}

		if (strchr(".", ent->d_name[0]) != NULL && !(config->options & FORCE)) {
			continue;
		}

		if (fstatat(statfd, ent->d_name, &buffer, 0) < 0)
			continue;

		if (IsRepairScriptConfig(ent->d_name) == 0) {
			if (S_ISREG(buffer.st_mode) == 0) {
				continue;
			}

			if (!(buffer.st_mode & S_IXUSR))
				continue;

			if (!(buffer.st_mode & S_IRUSR))
				continue;
		} else {
			if (S_ISREG(buffer.st_mode) == 0) {
				continue;
			}
		}

		repaircmd_t *cmd = (repaircmd_t *) calloc(1, sizeof(*cmd));

		if (cmd == NULL) {
			goto error;
		}

		for (size_t i = 0; i < strlen(repairScriptFolder); i += 1) {
			if (repairScriptFolder[i] == '/' && i < strlen(repairScriptFolder)
			    && repairScriptFolder[i+1] == '\0') {
				repairScriptFolder[i] = '\0';
			}
		}

		Wasprintf((char **)&cmd->path, "%s/%s", repairScriptFolder, ent->d_name);

		if (cmd->path == NULL) {
			assert(cmd != NULL);
			free(cmd);
			goto error;
		}

		if (IsRepairScriptConfig(ent->d_name) == 0) {
			cmd->legacy = true;
		} else {
			//For V3 repair scripts cmd->path refers to the pathname of the repair script config file
			if (LoadRepairScriptLink
			    (&cmd->spawnattr, (char *)cmd->path) == false) {
				free((void *)cmd->path);
				free(cmd);
				continue;
			}

			cmd->spawnattr.repairFilePathname = strdup(cmd->path);
			free((void *)cmd->path);
			cmd->path = NULL;
			cmd->path = cmd->spawnattr.execStart;

			char * rel = basename(strdup(cmd->path));

			if (strcmp(rel, cmd->path) == 0) {
				free((void*)rel);
				Wasprintf((char **)&rel, "%s/%s", repairScriptFolder, cmd->path);
				free((void*)cmd->path);
				cmd->path = cmd->spawnattr.execStart = rel;
			}

			if (cmd->path == NULL) {
				fprintf(stderr,
					"Ignoring malformed repair file: %s\n",
					ent->d_name);
				free(cmd);
				continue;
			}

			if (fd < 0) {
				fprintf(stderr, "unable to open file %s:\n",
					MyStrerror(errno));
				free((void *)cmd->path);
				free((void *)cmd);
				continue;
			}

			if (IsExe(cmd->path, false) < 0) {
				fprintf(stderr, "%s is not an executable\n",
					cmd->path);
				free((void *)cmd->path);
				free((void *)cmd);
				continue;
			}

			cmd->legacy = false;
		}

		list_add(&cmd->entry, &p->head);
	}

	assert(fd != -1);

	close(fd);
	closedir(dir);
	DeleteDuplicates(p);
	return 0;

 error:
	assert(fd != -1);
	close(fd);
	Logmsg(LOG_ERR, "watchdogd: %s", MyStrerror(errno));
	closedir(dir);

	return -1;
}

void FreeExeList(ProcessList * p)
{
	assert(p != NULL);

	repaircmd_t *c = NULL;
	repaircmd_t *next = NULL;

	list_for_each_entry(c, next, &p->head, entry) {
		list_del(&c->entry);
		free((void *)c->path);
		if (c->legacy == false) {
			free((void *)c->spawnattr.user);
			free((void *)c->spawnattr.group);
			free((void *)c->spawnattr.workingDirectory);
			free((void *)c->spawnattr.repairFilePathname);
			free((void *)c->spawnattr.noNewPrivileges);
		}
		free(c);
	}
}

static void * __ExecScriptWorkerThread(void *a)
{
	assert(a != NULL);

	__sync_synchronize();

	Container *container = (Container *) a;
	repaircmd_t *c = container->cmd;
	container->workerThreadCount += 1;
	sem = 1;
	FutexWake(&sem);
	__sync_synchronize();

	if (c->legacy == false) {
		if (c->retString[0] == '\0') {
			c->ret =
			    SpawnAttr(&c->spawnattr, c->path, c->path, c->mode == TEST ? "test": "repair",
				      NULL);
		} else {
			c->ret =
			    SpawnAttr(&c->spawnattr, c->path, c->path, c->mode == TEST ? "test": "repair", c->retString,
				      NULL);
		}
	} else {
		spawnattr_t attr = {
				.workingDirectory = NULL, .repairFilePathname = NULL,
	        		.execStart = NULL, .user = NULL, .group = NULL,
				.timeout = container->config->repairBinTimeout, .nice = 0, .umask = 0,
				.noNewPrivileges = false, .hasUmask = false
		};

		if (c->retString[0] == '\0') {
			if (c->mode == TEST) {
				c->ret = SpawnAttr(&attr, c->path, c->path, "test", NULL);
			} else {
				c->ret = SpawnAttr(&attr, c->path, c->path, "repair", c->path, NULL);
			}
		} else {
			if (c->mode == TEST) {
				c->ret = SpawnAttr(&attr, c->path, c->path, "test", NULL);
			} else {
				c->ret = SpawnAttr(&attr, c->path, c->path, "repair", c->retString, c->path, NULL);
			}
		}
	}

	c->retString[0] = '\0';

	container->workerThreadCount -= 1;

	__sync_synchronize();
	return NULL;
}

static void __WaitForWorkers(Container const *container)
{
	while (container->workerThreadCount != 0) {
		sleep(1);
	}
}

static int __ExecuteRepairScripts(void *a)
{
	struct executeScriptsStruct *arg = (struct executeScriptsStruct *)a;
	ProcessList *p = arg->list;
	struct cfgoptions *s = arg->config;

	Container container = {{0}, s, NULL};

	repaircmd_t *c = NULL;
	repaircmd_t *next = NULL;

	list_for_each_entry(c, next, &p->head, entry) {
		container.cmd = c;
		container.cmd->mode = TEST;

		c->retString[0] = '\0';
		ThreadPoolAddTask(__ExecScriptWorkerThread, &container, true);
		__sync_synchronize();
		FutexWait(&sem, 0);
		sem = 0;
	}

	c = NULL;
	next = NULL;

	__WaitForWorkers(&container);

	list_for_each_entry(c, next, &p->head, entry) {
		if (c->ret == 0) {
			continue;
		}

		container.cmd = c;
		portable_snprintf(container.cmd->retString, sizeof(container.cmd->retString), "%i", c->ret);

		container.cmd->mode = REPAIR;

		ThreadPoolAddTask(__ExecScriptWorkerThread, &container, true);
		__sync_synchronize();
		FutexWait(&sem, 0);
		sem = 0;
	}

	__WaitForWorkers(&container);

	c = NULL;
	next = NULL;

	list_for_each_entry(c, next, &p->head, entry) {
		if (c->ret != 0) {
			Logmsg(LOG_ERR, "repair %s script failed",
				c->legacy == false ? c->spawnattr.repairFilePathname : c->path);
			return 1;
		}
	}

	return 0;
}

static int pipeFd[2] = {0};

bool ExecuteRepairScriptsPreFork(ProcessList * p, struct cfgoptions *s)
{
	if (list_is_empty(&p->head)) {
		return true;
	}

	pipe(pipeFd);

	pid_t pid = fork();

	if (pid == -1) {
		Logmsg(LOG_ERR, "%s\n", MyStrerror(errno));
		return false;
	} else if (pid == 0) {
		close(pipeFd[0]);
		pid_t pid = fork();

#if defined(__linux__)
		if (LinuxRunningSystemd() == 1) {
			unsetenv("NOTIFY_SOCKET");
		}
#endif

		unsetenv("LD_PRELOAD");

		if (pid > 0) {
			_Exit(0);
		}

		if (pid < 0) {
			Logmsg(LOG_ERR, "fork failed: %s", MyStrerror(errno));
			abort();
		}

		char b[1];

		ThreadPoolNew();

		while (true) {
			uint64_t value = 0;
			struct executeScriptsStruct ess;
			ess.list = p;
			ess.config = s;

			int ret = __ExecuteRepairScripts(&ess);

			write(pipeFd[1], &ret, sizeof(ret));
		}

		exit(0);
	}
	close(pipeFd[1]);
	return true;
}

int ExecuteRepairScripts(void)
{
	uint64_t value = 1;
	int ret = 0;

	read(pipeFd[0], &ret, sizeof(ret));

	if (ret != 0) {
		return -1;
	}

	return 0;
}
<|endoftext|>


<commit_before>// "Hello World" in C++
#include <iostream>
using namespace std;

int main ()
{
  cout << "Heppy Valentine Day!"<<endl <<endl ;
  cout << "Heppy Valentine Day!"<<endl <<engl ;
  cout << "Heppy Valentine Day!"<<endl <<endl ;
  cout << "Heppy Valentine Day!"<<endl <<endl ;
  cout << "Heppy Valentine Day!"<<endl <<endl ;
  return 0;
}
<commit_msg>popravka grashka pri kompilaciq<commit_after>// "Hello World" in C++
#include <iostream>
using namespace std;

int main ()
{
  cout << "Heppy Valentine Day!"<<endl <<endl ;
  cout << "Heppy Valentine Day!"<<endl <<endl ;
  cout << "Heppy Valentine Day!"<<endl <<endl ;
  cout << "Heppy Valentine Day!"<<endl <<endl ;
  cout << "Heppy Valentine Day!"<<endl <<endl ;
  return 0;
}
<|endoftext|>


<commit_before>#include "cinder/app/App.h"
#include "cinder/Json.h"

#include "jsoncpp/json.h"
#include "catch.hpp"

using namespace ci;
using namespace ci::app;
using namespace std;

TEST_CASE("Json", "[noisy]")
{
	SECTION("Basic JSON Parsing")
	{
		console() << "jsoncpp version: " << JSONCPP_VERSION_STRING << endl;

		JsonTree value( "key", "value" );
		console() << value << endl;

		JsonTree doc( loadResource( "data/library.json" ) );
		JsonTree musicLibrary( doc.getChild( "library" ) );

		JsonTree owner = doc.getChild( "library.owner" );
		for( JsonTree::ConstIter item = owner.begin(); item != owner.end(); ++item ) {
			console() << "Node: " << item->getKey() << " Value: " << item->getValue<string>() << endl;
		}

		JsonTree tracks = doc.getChild( "library.albums[0].tracks" );
		for( JsonTree::ConstIter track = tracks.begin(); track != tracks.end(); ++track ) {
			console() << track->getChild( "id" ).getValue<int>() << endl;
		}

		for( JsonTree::ConstIter trackIt = tracks.begin(); trackIt != tracks.end(); ++trackIt ) {
			JsonTree track = * trackIt;
			console() << track["id"].getValue<int>() << endl;
		}

		JsonTree firstAlbum = doc.getChild( "library.albums[0]" );
		for( JsonTree::Iter child = firstAlbum.begin(); child != firstAlbum.end(); ++child ) {
			if ( !child->hasChildren() ) {
				console() << "Key: " << child->getKey() << "  Value: " << child->getValue<string>() << endl;
			}
		}

		console() << doc.getChild( "library.owner" );
		JsonTree &ownerCity = doc.getChild( "library.owner.city" );
		string s = ownerCity.getPath();
		console() << "Path: " << ownerCity.getPath() << "\n  Value: " << ownerCity.getValue<string>() << endl;
		console() << doc;

		JsonTree firstTrackCopy = doc.getChild( "library.albums[0].tracks[0].title" );
		firstTrackCopy = JsonTree( firstTrackCopy.getKey(), string( "Replacement name" ) );
		console() << doc.getChild( "library.albums[0].tracks[0]['title']" ) << endl;

		JsonTree &firstTrackRef = doc.getChild( "library.albums[0].tracks[2].title" );
		console() << firstTrackRef.getPath() << endl;
		firstTrackRef = JsonTree( firstTrackRef.getKey(), string( "Replacement name" ) );
		console() << doc.getChild( "library.albums[0].tracks[0].title" ) << endl;

		console() << "attempting invalid json (should cause ExcJsonParserError next).." << endl;
		try {
			JsonTree invalid( "%%%%%%%%" );
		} catch ( JsonTree::ExcJsonParserError ex ) {
			console() << ex.what() << endl;
		}

		JsonTree test32u( "uint32", uint32_t( math<uint64_t>::pow( 2, 32 ) ) - 1 );
		console() << test32u;
		console() << test32u.getValue() << endl;
		JsonTree test32( "int32", int32_t( math<int32_t>::pow( 2, 32 ) ) - 1 );
		console() << test32;
		console() << test32.getValue() << endl;
		JsonTree test64u( "uint64", uint64_t( math<uint64_t>::pow( 2, 64 ) ) - 1 );
		console() << test64u;
		console() << test64u.getValue() << endl;
		JsonTree test64( "int64", int64_t( math<int64_t>::pow( 2, 64 ) ) - 1 );
		console() << test64;
		console() << test64.getValue() << endl;

		console() << "complete." << endl;
	}

	SECTION("Cinder ignores c-style comments in JSON")
	{
		console() << "testing json with comments.." << endl;

		try {
			JsonTree json( loadFile( "data/test_comments.json" ) );
			console() << "test_comments.json parsed contents: " << json << endl;
		}
		catch( ci::JsonTree::Exception &exc ) {
			console() << "caught json exception, what: " << exc.what() << endl;
		}
		catch( std::exception &exc ) {
			console() << "Other exception, what: " << exc.what() << endl;
		}
	}

	SECTION("Cinder can build and write JSON trees to disk")
	{
		JsonTree doc;
		JsonTree library = JsonTree::makeObject( "library" );
		JsonTree album = JsonTree::makeArray( "album" );

		album.addChild(
			JsonTree( "musician", string( "Sufjan Stevens" ) ) ).addChild(
			JsonTree( "year", string( "2004" ) ) ).addChild(
			JsonTree( "title", string( "Seven Swans" ) )
			);

		JsonTree tracks = JsonTree::makeArray( "tracks" );

		for ( int32_t i = 0; i < 6; i ++ ) {

			JsonTree track;
			track.pushBack( JsonTree( "id", i + 1 ) );

			JsonTree title;
			switch ( i ) {
			case 0:
				title = JsonTree( "title", "All the Trees of the Field Will Clap Their Hands" );
				break;
			case 1:
				title = JsonTree( "title", "The Dress Looks Nice on You" );
				break;
			case 2:
				title = JsonTree( "title", "In the Dev Hole's Territory" );
				break;
			case 3:
				title = JsonTree( "title", "To Be a Clone With You" );
				break;
			case 4:
				title = JsonTree( "title", "To Be Removed" );
				break;
			case 5:
				title = JsonTree( "title", "To Be Removed" );
				break;
			}

			track.addChild( title ).addChild( track );
			tracks.pushBack( track );
		}

		for ( JsonTree::Iter trackIt = tracks.begin(); trackIt != tracks.end(); ++trackIt ) {
			if ( trackIt->getChild( "id" ).getValue<int>() == 3 ) {
				tracks.replaceChild( trackIt, JsonTree().addChild( JsonTree( "id", 3 ) ).addChild( JsonTree( "title", "In the Devil's Territory" ) ) );
			}
		}

		tracks.replaceChild( 3, JsonTree().addChild( JsonTree( "id", 4 ) ).addChild( JsonTree( "title", "To Be Alone With You" ) ) );

		tracks.removeChild( 4 );

		for ( JsonTree::Iter trackIt = tracks.begin(); trackIt != tracks.end(); ) {
			if ( trackIt->getChild( "id" ).getValue<int>() == 6 ) {
				trackIt = tracks.removeChild( trackIt );
			} else {
				++trackIt;
			}
		}

		album.pushBack( tracks );
		library.pushBack( album );
		doc.pushBack( library );

		console() << doc;

		doc.write( writeFile( getDocumentsDirectory() / "testoutput.json" ), JsonTree::WriteOptions() );
		doc.write( writeFile( getDocumentsDirectory() / "testoutput_fast.json" ), JsonTree::WriteOptions().indented( false ) );
	}
} // json
<commit_msg>data file load changes for xplatform friendliness<commit_after>#include "cinder/app/App.h"
#include "cinder/Json.h"

#include "jsoncpp/json.h"
#include "catch.hpp"

using namespace ci;
using namespace ci::app;
using namespace std;

TEST_CASE("Json", "[noisy]")
{
	SECTION("Basic JSON Parsing")
	{
		console() << "jsoncpp version: " << JSONCPP_VERSION_STRING << endl;

		JsonTree value( "key", "value" );
		console() << value << endl;

		JsonTree doc( loadFile( "data/library.json" ) );
		JsonTree musicLibrary( doc.getChild( "library" ) );

		JsonTree owner = doc.getChild( "library.owner" );
		for( JsonTree::ConstIter item = owner.begin(); item != owner.end(); ++item ) {
			console() << "Node: " << item->getKey() << " Value: " << item->getValue<string>() << endl;
		}

		JsonTree tracks = doc.getChild( "library.albums[0].tracks" );
		for( JsonTree::ConstIter track = tracks.begin(); track != tracks.end(); ++track ) {
			console() << track->getChild( "id" ).getValue<int>() << endl;
		}

		for( JsonTree::ConstIter trackIt = tracks.begin(); trackIt != tracks.end(); ++trackIt ) {
			JsonTree track = * trackIt;
			console() << track["id"].getValue<int>() << endl;
		}

		JsonTree firstAlbum = doc.getChild( "library.albums[0]" );
		for( JsonTree::Iter child = firstAlbum.begin(); child != firstAlbum.end(); ++child ) {
			if ( !child->hasChildren() ) {
				console() << "Key: " << child->getKey() << "  Value: " << child->getValue<string>() << endl;
			}
		}

		console() << doc.getChild( "library.owner" );
		JsonTree &ownerCity = doc.getChild( "library.owner.city" );
		string s = ownerCity.getPath();
		console() << "Path: " << ownerCity.getPath() << "\n  Value: " << ownerCity.getValue<string>() << endl;
		console() << doc;

		JsonTree firstTrackCopy = doc.getChild( "library.albums[0].tracks[0].title" );
		firstTrackCopy = JsonTree( firstTrackCopy.getKey(), string( "Replacement name" ) );
		console() << doc.getChild( "library.albums[0].tracks[0]['title']" ) << endl;

		JsonTree &firstTrackRef = doc.getChild( "library.albums[0].tracks[2].title" );
		console() << firstTrackRef.getPath() << endl;
		firstTrackRef = JsonTree( firstTrackRef.getKey(), string( "Replacement name" ) );
		console() << doc.getChild( "library.albums[0].tracks[0].title" ) << endl;

		console() << "attempting invalid json (should cause ExcJsonParserError next).." << endl;
		try {
			JsonTree invalid( "%%%%%%%%" );
		} catch ( JsonTree::ExcJsonParserError ex ) {
			console() << ex.what() << endl;
		}

		JsonTree test32u( "uint32", uint32_t( math<uint64_t>::pow( 2, 32 ) ) - 1 );
		console() << test32u;
		console() << test32u.getValue() << endl;
		JsonTree test32( "int32", int32_t( math<int32_t>::pow( 2, 32 ) ) - 1 );
		console() << test32;
		console() << test32.getValue() << endl;
		JsonTree test64u( "uint64", uint64_t( math<uint64_t>::pow( 2, 64 ) ) - 1 );
		console() << test64u;
		console() << test64u.getValue() << endl;
		JsonTree test64( "int64", int64_t( math<int64_t>::pow( 2, 64 ) ) - 1 );
		console() << test64;
		console() << test64.getValue() << endl;

		console() << "complete." << endl;
	}

	SECTION("Cinder ignores c-style comments in JSON")
	{
		console() << "testing json with comments.." << endl;

		try {
			JsonTree json( loadFile( "data/test_comments.json" ) );
			console() << "test_comments.json parsed contents: " << json << endl;
		}
		catch( ci::JsonTree::Exception &exc ) {
			console() << "caught json exception, what: " << exc.what() << endl;
		}
		catch( std::exception &exc ) {
			console() << "Other exception, what: " << exc.what() << endl;
		}
	}

	SECTION("Cinder can build and write JSON trees to disk")
	{
		JsonTree doc;
		JsonTree library = JsonTree::makeObject( "library" );
		JsonTree album = JsonTree::makeArray( "album" );

		album.addChild(
			JsonTree( "musician", string( "Sufjan Stevens" ) ) ).addChild(
			JsonTree( "year", string( "2004" ) ) ).addChild(
			JsonTree( "title", string( "Seven Swans" ) )
			);

		JsonTree tracks = JsonTree::makeArray( "tracks" );

		for ( int32_t i = 0; i < 6; i ++ ) {

			JsonTree track;
			track.pushBack( JsonTree( "id", i + 1 ) );

			JsonTree title;
			switch ( i ) {
			case 0:
				title = JsonTree( "title", "All the Trees of the Field Will Clap Their Hands" );
				break;
			case 1:
				title = JsonTree( "title", "The Dress Looks Nice on You" );
				break;
			case 2:
				title = JsonTree( "title", "In the Dev Hole's Territory" );
				break;
			case 3:
				title = JsonTree( "title", "To Be a Clone With You" );
				break;
			case 4:
				title = JsonTree( "title", "To Be Removed" );
				break;
			case 5:
				title = JsonTree( "title", "To Be Removed" );
				break;
			}

			track.addChild( title ).addChild( track );
			tracks.pushBack( track );
		}

		for ( JsonTree::Iter trackIt = tracks.begin(); trackIt != tracks.end(); ++trackIt ) {
			if ( trackIt->getChild( "id" ).getValue<int>() == 3 ) {
				tracks.replaceChild( trackIt, JsonTree().addChild( JsonTree( "id", 3 ) ).addChild( JsonTree( "title", "In the Devil's Territory" ) ) );
			}
		}

		tracks.replaceChild( 3, JsonTree().addChild( JsonTree( "id", 4 ) ).addChild( JsonTree( "title", "To Be Alone With You" ) ) );

		tracks.removeChild( 4 );

		for ( JsonTree::Iter trackIt = tracks.begin(); trackIt != tracks.end(); ) {
			if ( trackIt->getChild( "id" ).getValue<int>() == 6 ) {
				trackIt = tracks.removeChild( trackIt );
			} else {
				++trackIt;
			}
		}

		album.pushBack( tracks );
		library.pushBack( album );
		doc.pushBack( library );

		console() << doc;

		doc.write( writeFile( getDocumentsDirectory() / "testoutput.json" ), JsonTree::WriteOptions() );
		doc.write( writeFile( getDocumentsDirectory() / "testoutput_fast.json" ), JsonTree::WriteOptions().indented( false ) );
	}
} // json
<|endoftext|>