<commit_before>// Title       : Implementation of Coroutine in Cpp
// Author      : hanzh.xu@gmail.com
// Date        : 11-21-2020
// License     : MIT License

/*
Implementation of Coroutine in Cpp

Compiler:
// clang version 3.8.1-24+rpi1 (tags/RELEASE_381/final)
// Target: armv6--linux-gnueabihf
// Thread model: posix
// clang -std=c++0x -lstdc++

Usage:
// class MyGen        : public Gen<Output type of the generator>
class OneMoreHanoiGen : public Gen<string> {
public:
    // Local variables of the generator.
    int n;
    string a, b, c;
    shared_ptr<Gen<string> > iter;

    // Constructor of the generator.
    OneMoreHanoiGen(int _n, string _a, string _b, string _c):
        n(_n), a(_a), b(_b), c(_c) {}

    // Write your code in the step method.
    // It is very straight forward.
    // You just need to replace all control statements with the MACRO in your generator.
    // bool step(string& output);
    // Args:
    //   output: the output of your generator, set the output before doing yield.
    // Return:
    //    The return value is used by the framework.
    //    You don't need to return true or false by yourself, and the MACRO will take care of it.
    bool step(string& output) {
        // Declare all the control statements at first.
        // IMPORTANT: You can NOT use a control MACRO without declaring its name.
        // DEC_BEG : begin the declaration.
        // DEF_IF(if_name) : declare a if statement named if_name.
        // DEF_LOOP(loop_name) : declare a loop statement named loop_name.
        // DEC_YIELD(yield_name) : declare a loop statement named yield_name.
        // DEC_END : end the declaration.
        DEC_BEG
            DEC_IF(if1), DEC_LOOP(loop1), DEC_LOOP(loop2), DEC_LOOP(loop3),
            DEC_YIELD(y1), DEC_YIELD(y2), DEC_YIELD(y3), DEC_YIELD(y4)
        DEC_END

        // Using the control MACRO to write the code.
        // PRG_BEG                                       -> Begin the program.
        //   IF(name, condition, true_block, false_block); -> A if statment with name.
        //   WHILE(name, condition loop_block);            -> A while loop with name.
        //   BREAK(loop_name);                             -> Jump to the end of the loop named loop_name
        //   CONTINUE(loop_name);                          -> Jump to the begin of the loop named loop_name
        //   YIELD(name);                                  -> A yield statement with name.
        //   RETURN();                                     -> Finish the generator.
        // PRG_END                                       -> End the program.
        PRG_BEG
        IF(if1, n == 1, {
            output = a + " --> " + c;
            YIELD(y1);
        }, {
            iter = make_shared<OneMoreHanoiGen>(n - 1, a, c, b);
            WHILE(loop1, iter->next(output), YIELD(y2));
            iter = make_shared<OneMoreHanoiGen>(1, a, b, c);
            WHILE(loop2, iter->next(output), YIELD(y3));
            iter = make_shared<OneMoreHanoiGen>(n - 1, b, a, c);
            WHILE(loop3, iter->next(output), YIELD(y4));
        });
        PRG_END
    }
};

int main() {
    string output;

    // Build a HanoiGen with Args (3, "A", "B", "C").
    OneMoreHanoiGen hanoiGen(3, "A", "B", "C");

    // Get the next output, until the generator returns false.
    // bool isAlive = hanoiGen(output);
    // if(isAlive) cout << output << endl;
    while(hanoiGen(output)) cout << output << endl;

    return 0;
}

// You also can create a coroutine having full functionality, if you want to do some interactive operations with the coroutine.
// The only difference is that the step method has an extra argument input now.
// The input argument represents the input variable that you pass into the Coroutine.
// See the example class GuessNumber to know how to use it.
template<typename S, typename T>
class Coroutine : public std::enable_shared_from_this<Coroutine<S,T>> {
public:
    virtual bool step(S& input, T& output) = 0;
*/

#include <cstdlib>
#include <ctime>
#include <iostream>
#include <functional>
#include <memory>
#include <string>
#include <tuple>
#include <typeinfo>
#include <utility>
#include <vector>

using namespace std;

template<typename S>
class Source : public std::enable_shared_from_this<Source<S>> {
public:
	virtual ~Source() {}
    virtual bool operator()(S& output) = 0;
    bool next(S& output) {
        return (*this)(output);
    }
    shared_ptr<Source<S>> getPtr() { return this->shared_from_this(); }
};

template<typename S>
class Gen : public Source<S> {
public:
    int state;
    bool isAlive;
    Gen() : state(0), isAlive(true) {}
    virtual bool step(S& output) = 0;
    bool operator()(S& output) {
        while(!step(output));
        return isAlive;
    }
};

template<typename S, typename T>
class Coroutine : public std::enable_shared_from_this<Coroutine<S,T>> {
public:
    int state;
    bool isAlive;
    Coroutine() : state(0), isAlive(true) {}

    virtual ~Coroutine() {}
    virtual bool step(S& input, T& output) = 0;

    bool next(S& input, T& output) {
        while(!step(input, output));
        return isAlive;
    }
    bool operator()(S& input, T& output) {
        return next(input, output);
    }
    shared_ptr<Coroutine<S,T>> getPtr() { return this->shared_from_this(); }
};

#define PRG_BEG \
switch(state) { \
case PBEG: {}

#define PRG_END \
case PEND: {} \
default: { isAlive = false; return true; } }

#define BEG(name) BEG_##name
#define ELSE(name) ELSE_##name
#define END(name) END_##name

#define IF(name,c,a,b) \
case BEG(name): { if(c) { {a;} state = END(name); return false; } else { state = ELSE(name); } } \
case ELSE(name): { b; } \
case END(name): {}

#define LOOP(name,s) \
case BEG(name): { {s;} state = BEG(name); return false; } \
case END(name): {}

#define WHILE(name,c,s) \
case BEG(name): { if(!(c)) { state = END(name); return false; } {s;} state = BEG(name); return false; } \
case END(name): {}

#define YIELD(name) \
case BEG(name): { state = END(name); isAlive = true; return true; } \
case END(name): {}

#define CONTINUE(loop) { state = BEG(loop); return false; }
#define BREAK(loop) { state = END(loop); return false; }

#define GOTO(label) { state = label; return false; }

#define RETURN() { state = PEND; return false; }

#define DEC_BEG enum { PBEG = 0, PEND,
#define DEC_IF(name) BEG(name), ELSE(name), END(name)
#define DEC_LOOP(name) BEG(name), END(name)
#define DEC_YIELD(name) BEG(name), END(name)
#define DEC_END };

/*
L: def prod_iter(s):
0:   if len(s) == 0:
1:     yield []
2:   else:
3:     x = 0
4:     while true:
5:       xs = []
6:       iter = generator.create(prod_iter(s[1:]))
7:       while true:
8:         xs, isAlive = iter.resume()
9:         if !isAlive:
10           break
11         yield [x] + xs
12       x += 1
13       if x >= s[0]:
14         break
-1   return
*/
class OneMoreProdGen : public Gen<vector<int> > {
public:
    vector<unsigned int> s;
    int x;
    shared_ptr<Source<vector<int> > > iter;
    vector<int> xs;
    OneMoreProdGen(const vector<unsigned int>& _s) : s(_s) {}
    bool step(vector<int>& output) {
        DEC_BEG
            DEC_IF(if1), DEC_IF(if2), DEC_IF(if3),
            DEC_LOOP(loop1), DEC_LOOP(loop2),
            DEC_YIELD(y1), DEC_YIELD(y2)
        DEC_END
        PRG_BEG
        IF(if1, s.size()==0, {
            output.clear();
            YIELD(y1);
        }, {
            x = 0;
            WHILE(loop1, true, {
                IF(if3, x >= s[0], BREAK(loop1), {});
                {
                vector<unsigned int> ss(s.begin() + 1, s.end());
                iter = make_shared<OneMoreProdGen>(ss);
                }
                WHILE(loop2, iter->next(xs), {
                    output.clear();
                    output.push_back(x);
                    output.insert(output.end(), xs.begin(), xs.end());
                    YIELD(y2);
                });
                x += 1;
            })
        });
        PRG_END
    }
};

/*
def hanoi(n, a, b, c):
    if n == 1:
        s = str(a) +  ' --> ' + str(c)
        yield s
    else:
        for s in hanoi(n - 1, a, c, b):
            yield s
        for s in hanoi(1    , a, b, c):
            yield s
        for s in hanoi(n - 1, b, a, c):
            yield s
*/
class OneMoreHanoiGen : public Gen<string> {
public:
    int n;
    string a, b, c;
    shared_ptr<Gen<string> > iter;
    OneMoreHanoiGen(int _n, string _a, string _b, string _c):
        n(_n), a(_a), b(_b), c(_c) {}
    bool step(string& output) {
        DEC_BEG
            DEC_IF(if1), DEC_LOOP(loop1), DEC_LOOP(loop2), DEC_LOOP(loop3),
            DEC_YIELD(y1), DEC_YIELD(y2), DEC_YIELD(y3), DEC_YIELD(y4)
        DEC_END
        PRG_BEG
        IF(if1, n == 1, {
            output = a + " --> " + c;
            YIELD(y1);
        }, {
            iter = make_shared<OneMoreHanoiGen>(n - 1, a, c, b);
            WHILE(loop1, iter->next(output), YIELD(y2));
            iter = make_shared<OneMoreHanoiGen>(1, a, b, c);
            WHILE(loop2, iter->next(output), YIELD(y3));
            iter = make_shared<OneMoreHanoiGen>(n - 1, b, a, c);
            WHILE(loop3, iter->next(output), YIELD(y4));
        });
        PRG_END
    }
};

class PrimeGen : public Gen<int> {
public:
    vector<int> primes;
    int i, j;
    PrimeGen() {}
    bool step(int& output) {
        DEC_BEG
            DEC_IF(if1), DEC_IF(if2),
            DEC_LOOP(loop1), DEC_LOOP(loop2),
            DEC_YIELD(y1)
        DEC_END
        PRG_BEG
        i = 2;
        WHILE(loop1, true, {
            j = 0;
            WHILE(loop2, j < primes.size(), {
               IF(if1, i % primes[j] == 0, {i++; CONTINUE(loop1);}, j++);
            });
            primes.push_back(i);
            output = i;
            YIELD(y1);
        });
        PRG_END
    }
};

class GuessNumber : public Coroutine<int, int> {
public:
    int t, num;
    GuessNumber() {}
    bool step(int& input, int& output) {
        DEC_BEG
            DEC_IF(if1), DEC_IF(if2),
            DEC_LOOP(loop1), DEC_LOOP(loop2),
            DEC_YIELD(y1), DEC_YIELD(y2)
        DEC_END
        PRG_BEG
        t = 0;
        srand(time(0));
        cout << "Guess a number between 0 and 100!" << endl;
        WHILE(loop1, true, {
            cout << "Match " << t << endl;
            num = rand() % 100;
            cout << "input a number:";
            YIELD(y1);
            WHILE(loop2, input != num, {
                IF(if2, input == -1, BREAK(loop1), {});
                IF(if1, input < num, {
                    cout << "Too small!" << endl;
                    output = -1;
                }, {
                    cout << "Too large!" << endl;
                    output = 1;
                });
                cout << "input a number agian:";
                YIELD(y2);
            });
            cout << "Bingo! It's " << num << "!" << endl;
            cout << "Let's play it again!" << endl;
            t++;
            output = 0;
        });
        cout << "ByeBye!" << endl;
        PRG_END
    }
};

template<typename T>
void print(vector<T>& vec) {
    for(int i = 0; i < vec.size(); ++i) {
        cout << vec[i] << " ";
    }
    cout << endl;
}

void testGuessNumber() {
    GuessNumber guess;
    int num, output;
    guess(num, output);
    do {
        cin >> num;
    } while(guess(num, output));
}

int main() {
    cout << "HanoiGen" << endl;
    string s;
    OneMoreHanoiGen hanoiGen(3, "A", "B", "C");
    while(hanoiGen(s)) cout << s << endl;

    cout << "CartesianProduct" << endl;
    vector<unsigned int> dimSize({2,3,4});
    vector<int> output(dimSize.size());
    OneMoreProdGen prodGen(dimSize);
    while(prodGen(output)) print(output);

    cout << "Prime numbers" << endl;
    PrimeGen primeGen;
    int p;
    for(int i = 0; i < 30; ++i) {
        primeGen(p);
        cout << p << " ";
    }
    cout << endl;

    testGuessNumber();
    return 0;
}
<commit_msg>Update macro_yield.cpp<commit_after>// Title       : Implementation of Coroutine in Cpp
// Author      : hanzh.xu@gmail.com
// Date        : 11-21-2020
// License     : MIT License

/*
Implementation of Coroutine in Cpp

Compiler:
// clang version 3.8.1-24+rpi1 (tags/RELEASE_381/final)
// Target: armv6--linux-gnueabihf
// Thread model: posix
// clang -std=c++0x -lstdc++

Usage:
// class MyGen        : public Gen<Output type of the generator>
class OneMoreHanoiGen : public Gen<string> {
public:
    // Local variables of the generator.
    int n;
    string a, b, c;
    shared_ptr<Gen<string> > iter;

    // Constructor of the generator.
    OneMoreHanoiGen(int _n, string _a, string _b, string _c):
        n(_n), a(_a), b(_b), c(_c) {}

    // Write your code in the step method.
    // It is very straight forward.
    // You just need to replace all control statements with the MACRO in your generator.
    // bool step(string& output);
    // Args:
    //   output: the output of your generator, set the output before doing yield.
    // Return:
    //    The return value is used by the framework.
    //    DO NOT return true or false by yourself, let the MACRO takes care of it.
    bool step(string& output) {
        // Declare all the control statements at first.
        // IMPORTANT: You can NOT use a control MACRO without declaring its name.
        // DEC_BEG : begin the declaration.
        // DEF_IF(if_name) : declare a if statement named if_name.
        // DEF_LOOP(loop_name) : declare a loop statement named loop_name.
        // DEC_YIELD(yield_name) : declare a loop statement named yield_name.
        // DEC_END : end the declaration.
        DEC_BEG
            DEC_IF(if1), DEC_LOOP(loop1), DEC_LOOP(loop2), DEC_LOOP(loop3),
            DEC_YIELD(y1), DEC_YIELD(y2), DEC_YIELD(y3), DEC_YIELD(y4)
        DEC_END

        // Using the control MACRO to write the code.
        // PRG_BEG                                       -> Begin the program.
        //   IF(name, condition, true_block, false_block); -> A if statment with name.
        //   WHILE(name, condition loop_block);            -> A while loop with name.
        //   BREAK(loop_name);                             -> Jump to the end of the loop named loop_name
        //   CONTINUE(loop_name);                          -> Jump to the begin of the loop named loop_name
        //   YIELD(name);                                  -> A yield statement with name.
        //   RETURN();                                     -> Finish the generator.
        // PRG_END                                       -> End the program.
        PRG_BEG
        IF(if1, n == 1, {
            output = a + " --> " + c;
            YIELD(y1);
        }, {
            iter = make_shared<OneMoreHanoiGen>(n - 1, a, c, b);
            WHILE(loop1, iter->next(output), YIELD(y2));
            iter = make_shared<OneMoreHanoiGen>(1, a, b, c);
            WHILE(loop2, iter->next(output), YIELD(y3));
            iter = make_shared<OneMoreHanoiGen>(n - 1, b, a, c);
            WHILE(loop3, iter->next(output), YIELD(y4));
        });
        PRG_END
    }
};

int main() {
    string output;

    // Build a HanoiGen with Args (3, "A", "B", "C").
    OneMoreHanoiGen hanoiGen(3, "A", "B", "C");

    // Get the next output, until the generator returns false.
    // bool isAlive = hanoiGen(output);
    // if(isAlive) cout << output << endl;
    while(hanoiGen(output)) cout << output << endl;

    return 0;
}

// You also can create a coroutine having full functionality, if you want to do some interactive operations with the coroutine.
// The only difference is that the step method has an extra argument input now.
// The input argument represents the input variable that you pass into the Coroutine.
// See the example class GuessNumber to know how to use it.
template<typename S, typename T>
class Coroutine : public std::enable_shared_from_this<Coroutine<S,T>> {
public:
    virtual bool step(S& input, T& output) = 0;
*/

#include <cstdlib>
#include <ctime>
#include <iostream>
#include <functional>
#include <memory>
#include <string>
#include <tuple>
#include <typeinfo>
#include <utility>
#include <vector>

using namespace std;

template<typename S>
class Source : public std::enable_shared_from_this<Source<S>> {
public:
	virtual ~Source() {}
    virtual bool operator()(S& output) = 0;
    bool next(S& output) {
        return (*this)(output);
    }
    shared_ptr<Source<S>> getPtr() { return this->shared_from_this(); }
};

template<typename S>
class Gen : public Source<S> {
public:
    int state;
    bool isAlive;
    Gen() : state(0), isAlive(true) {}
    virtual bool step(S& output) = 0;
    bool operator()(S& output) {
        while(!step(output));
        return isAlive;
    }
};

template<typename S, typename T>
class Coroutine : public std::enable_shared_from_this<Coroutine<S,T>> {
public:
    int state;
    bool isAlive;
    Coroutine() : state(0), isAlive(true) {}

    virtual ~Coroutine() {}
    virtual bool step(S& input, T& output) = 0;

    bool next(S& input, T& output) {
        while(!step(input, output));
        return isAlive;
    }
    bool operator()(S& input, T& output) {
        return next(input, output);
    }
    shared_ptr<Coroutine<S,T>> getPtr() { return this->shared_from_this(); }
};

#define PRG_BEG \
switch(state) { \
case PBEG: {}

#define PRG_END \
case PEND: {} \
default: { isAlive = false; return true; } }

#define BEG(name) BEG_##name
#define ELSE(name) ELSE_##name
#define END(name) END_##name

#define IF(name,c,a,b) \
case BEG(name): { if(c) { {a;} state = END(name); return false; } else { state = ELSE(name); } } \
case ELSE(name): { b; } \
case END(name): {}

#define LOOP(name,s) \
case BEG(name): { {s;} state = BEG(name); return false; } \
case END(name): {}

#define WHILE(name,c,s) \
case BEG(name): { if(!(c)) { state = END(name); return false; } {s;} state = BEG(name); return false; } \
case END(name): {}

#define YIELD(name) \
case BEG(name): { state = END(name); isAlive = true; return true; } \
case END(name): {}

#define CONTINUE(loop) { state = BEG(loop); return false; }
#define BREAK(loop) { state = END(loop); return false; }

#define GOTO(label) { state = label; return false; }

#define RETURN() { state = PEND; return false; }

#define DEC_BEG enum { PBEG = 0, PEND,
#define DEC_IF(name) BEG(name), ELSE(name), END(name)
#define DEC_LOOP(name) BEG(name), END(name)
#define DEC_YIELD(name) BEG(name), END(name)
#define DEC_END };

/*
L: def prod_iter(s):
0:   if len(s) == 0:
1:     yield []
2:   else:
3:     x = 0
4:     while true:
5:       xs = []
6:       iter = generator.create(prod_iter(s[1:]))
7:       while true:
8:         xs, isAlive = iter.resume()
9:         if !isAlive:
10           break
11         yield [x] + xs
12       x += 1
13       if x >= s[0]:
14         break
-1   return
*/
class OneMoreProdGen : public Gen<vector<int> > {
public:
    vector<unsigned int> s;
    int x;
    shared_ptr<Source<vector<int> > > iter;
    vector<int> xs;
    OneMoreProdGen(const vector<unsigned int>& _s) : s(_s) {}
    bool step(vector<int>& output) {
        DEC_BEG
            DEC_IF(if1), DEC_IF(if2), DEC_IF(if3),
            DEC_LOOP(loop1), DEC_LOOP(loop2),
            DEC_YIELD(y1), DEC_YIELD(y2)
        DEC_END
        PRG_BEG
        IF(if1, s.size()==0, {
            output.clear();
            YIELD(y1);
        }, {
            x = 0;
            WHILE(loop1, true, {
                IF(if3, x >= s[0], BREAK(loop1), {});
                {
                vector<unsigned int> ss(s.begin() + 1, s.end());
                iter = make_shared<OneMoreProdGen>(ss);
                }
                WHILE(loop2, iter->next(xs), {
                    output.clear();
                    output.push_back(x);
                    output.insert(output.end(), xs.begin(), xs.end());
                    YIELD(y2);
                });
                x += 1;
            })
        });
        PRG_END
    }
};

/*
def hanoi(n, a, b, c):
    if n == 1:
        s = str(a) +  ' --> ' + str(c)
        yield s
    else:
        for s in hanoi(n - 1, a, c, b):
            yield s
        for s in hanoi(1    , a, b, c):
            yield s
        for s in hanoi(n - 1, b, a, c):
            yield s
*/
class OneMoreHanoiGen : public Gen<string> {
public:
    int n;
    string a, b, c;
    shared_ptr<Gen<string> > iter;
    OneMoreHanoiGen(int _n, string _a, string _b, string _c):
        n(_n), a(_a), b(_b), c(_c) {}
    bool step(string& output) {
        DEC_BEG
            DEC_IF(if1), DEC_LOOP(loop1), DEC_LOOP(loop2), DEC_LOOP(loop3),
            DEC_YIELD(y1), DEC_YIELD(y2), DEC_YIELD(y3), DEC_YIELD(y4)
        DEC_END
        PRG_BEG
        IF(if1, n == 1, {
            output = a + " --> " + c;
            YIELD(y1);
        }, {
            iter = make_shared<OneMoreHanoiGen>(n - 1, a, c, b);
            WHILE(loop1, iter->next(output), YIELD(y2));
            iter = make_shared<OneMoreHanoiGen>(1, a, b, c);
            WHILE(loop2, iter->next(output), YIELD(y3));
            iter = make_shared<OneMoreHanoiGen>(n - 1, b, a, c);
            WHILE(loop3, iter->next(output), YIELD(y4));
        });
        PRG_END
    }
};

class PrimeGen : public Gen<int> {
public:
    vector<int> primes;
    int i, j;
    PrimeGen() {}
    bool step(int& output) {
        DEC_BEG
            DEC_IF(if1), DEC_IF(if2),
            DEC_LOOP(loop1), DEC_LOOP(loop2),
            DEC_YIELD(y1)
        DEC_END
        PRG_BEG
        i = 2;
        WHILE(loop1, true, {
            j = 0;
            WHILE(loop2, j < primes.size(), {
               IF(if1, i % primes[j] == 0, {i++; CONTINUE(loop1);}, j++);
            });
            primes.push_back(i);
            output = i;
            YIELD(y1);
        });
        PRG_END
    }
};

class GuessNumber : public Coroutine<int, int> {
public:
    int t, num;
    GuessNumber() {}
    bool step(int& input, int& output) {
        DEC_BEG
            DEC_IF(if1), DEC_IF(if2),
            DEC_LOOP(loop1), DEC_LOOP(loop2),
            DEC_YIELD(y1), DEC_YIELD(y2)
        DEC_END
        PRG_BEG
        t = 0;
        srand(time(0));
        cout << "Guess a number between 0 and 100!" << endl;
        WHILE(loop1, true, {
            cout << "Match " << t << endl;
            num = rand() % 100;
            cout << "input a number:";
            YIELD(y1);
            WHILE(loop2, input != num, {
                IF(if2, input == -1, BREAK(loop1), {});
                IF(if1, input < num, {
                    cout << "Too small!" << endl;
                    output = -1;
                }, {
                    cout << "Too large!" << endl;
                    output = 1;
                });
                cout << "input a number agian:";
                YIELD(y2);
            });
            cout << "Bingo! It's " << num << "!" << endl;
            cout << "Let's play it again!" << endl;
            t++;
            output = 0;
        });
        cout << "ByeBye!" << endl;
        PRG_END
    }
};

template<typename T>
void print(vector<T>& vec) {
    for(int i = 0; i < vec.size(); ++i) {
        cout << vec[i] << " ";
    }
    cout << endl;
}

void testGuessNumber() {
    GuessNumber guess;
    int num, output;
    guess(num, output);
    do {
        cin >> num;
    } while(guess(num, output));
}

int main() {
    cout << "HanoiGen" << endl;
    string s;
    OneMoreHanoiGen hanoiGen(3, "A", "B", "C");
    while(hanoiGen(s)) cout << s << endl;

    cout << "CartesianProduct" << endl;
    vector<unsigned int> dimSize({2,3,4});
    vector<int> output(dimSize.size());
    OneMoreProdGen prodGen(dimSize);
    while(prodGen(output)) print(output);

    cout << "Prime numbers" << endl;
    PrimeGen primeGen;
    int p;
    for(int i = 0; i < 30; ++i) {
        primeGen(p);
        cout << p << " ";
    }
    cout << endl;

    testGuessNumber();
    return 0;
}
<|endoftext|>


<commit_before>#include"../header/IThreadPoolItemBase.hpp"
#include<utility>	//forward, move
#include"../../lib/header/thread/CSemaphore.hpp"
#include"../../lib/header/thread/CSmartThread.hpp"
using namespace std;

namespace nThread
{
	struct IThreadPoolItemBase::Impl
	{
		bool alive;
		CSemaphore wait;	//to wake up thr
		CSmartThread thr;	//must destroying before alive and wait
		function<void()> func;
		Impl();
		template<class FuncFwdRef>
		void exec(FuncFwdRef &&val)
		{
			func=forward<FuncFwdRef>(val);
			wake();
		}
		inline void wake()
		{
			wait.signal();
		}
		~Impl();
	};

	IThreadPoolItemBase::Impl::Impl()
		:alive{true},thr{[this]{
			while(wait.wait(),alive)
				func();
		}}{}

	IThreadPoolItemBase::Impl::~Impl()
	{
		alive=false;
		wake();
	}

	IThreadPoolItemBase::IThreadPoolItemBase()=default;

	IThreadPoolItemBase::IThreadPoolItemBase(IThreadPoolItemBase &&xval) noexcept=default;

	IThreadPoolItemBase::id IThreadPoolItemBase::get_id() const noexcept
	{
		return impl_.get().thr.get_id();
	}

	IThreadPoolItemBase& IThreadPoolItemBase::operator=(IThreadPoolItemBase &&xval) noexcept=default;

	IThreadPoolItemBase::~IThreadPoolItemBase()=default;

	void IThreadPoolItemBase::exec_(const function<void()> &val)
	{
		impl_.get().exec(val);
	}

	void IThreadPoolItemBase::exec_(function<void()> &&xval)
	{
		impl_.get().exec(move(xval));
	}
}<commit_msg>fix variable name<commit_after>#include"../header/IThreadPoolItemBase.hpp"
#include<utility>	//forward, move
#include"../../lib/header/thread/CSemaphore.hpp"
#include"../../lib/header/thread/CSmartThread.hpp"
using namespace std;

namespace nThread
{
	struct IThreadPoolItemBase::Impl
	{
		bool alive;
		CSemaphore wait;	//to wake up thr
		CSmartThread thr;	//must destroying before alive and wait
		function<void()> func;
		Impl();
		template<class FuncFwdRef>
		void exec(FuncFwdRef &&val)
		{
			func=forward<FuncFwdRef>(val);
			wake();
		}
		inline void wake()
		{
			wait.signal();
		}
		~Impl();
	};

	IThreadPoolItemBase::Impl::Impl()
		:alive{true},thr{[this]{
			while(wait.wait(),alive)
				func();
		}}{}

	IThreadPoolItemBase::Impl::~Impl()
	{
		alive=false;
		wake();
	}

	IThreadPoolItemBase::IThreadPoolItemBase()=default;

	IThreadPoolItemBase::IThreadPoolItemBase(IThreadPoolItemBase &&) noexcept=default;

	IThreadPoolItemBase::id IThreadPoolItemBase::get_id() const noexcept
	{
		return impl_.get().thr.get_id();
	}

	IThreadPoolItemBase& IThreadPoolItemBase::operator=(IThreadPoolItemBase &&) noexcept=default;

	IThreadPoolItemBase::~IThreadPoolItemBase()=default;

	void IThreadPoolItemBase::exec_(const function<void()> &val)
	{
		impl_.get().exec(val);
	}

	void IThreadPoolItemBase::exec_(function<void()> &&val)
	{
		impl_.get().exec(move(val));
	}
}<|endoftext|>


<commit_before>/*
    Copyright (C) 2009  George Kiagiadakis <kiagiadakis.george@gmail.com>

    This library is free software; you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published
    by the Free Software Foundation; either version 2.1 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "qgsttest.h"
#include <QGlib/Value>
#include <QGst/Object>

class ValueTest : public QGstTest
{
    Q_OBJECT
private Q_SLOTS:
    void intTest();
    void stringTest();
    void enumTest();
    void copyTest();
    void castTest();
    void qdebugTest();
};

void ValueTest::intTest()
{
    QGlib::Value v(10);
    QVERIFY(v.isValid());
    QCOMPARE(v.type(), QGlib::GetType<int>());
    QCOMPARE(v.get<int>(), 10);
}

void ValueTest::stringTest()
{
    QGlib::Value v;
    QVERIFY(!v.isValid());
    v.init<QString>();
    v.set(QString::fromUtf8("Γειά σου κόσμε"));
    QCOMPARE(v.type(), QGlib::GetType<QString>());
    QByteArray b = v.get<QByteArray>();
    QCOMPARE(QString::fromUtf8(b), QString::fromUtf8("Γειά σου κόσμε"));
    QCOMPARE(v.get<QString>(), QString::fromUtf8("Γειά σου κόσμε"));
}

void ValueTest::enumTest()
{
    QGlib::Value v;
    v.init<QGst::PadDirection>();
    v.set(QGst::PadSink);
    QVERIFY(v.isValid());
    QCOMPARE(v.type(), QGlib::GetType<QGst::PadDirection>());
    QCOMPARE(v.get<QGst::PadDirection>(), QGst::PadSink);
}

void ValueTest::copyTest()
{
    QGlib::Value v(10);

    QGlib::SharedValue sv(v);
    QVERIFY(sv.isValid());
    QCOMPARE(sv.type(), QGlib::GetType<int>());
    QCOMPARE(sv.get<int>(), 10);

    sv.set(20);
    QCOMPARE(v.get<int>(), 20);

    {
        QGlib::Value v2(sv);
        QVERIFY(v2.isValid());
        QCOMPARE(v2.type(), QGlib::GetType<int>());
        QCOMPARE(v2.get<int>(), 20);

        v2.set(30);
        QCOMPARE(v.get<int>(), 20);
        QCOMPARE(sv.get<int>(), 20);
        QCOMPARE(v2.get<int>(), 30);

        v2 = v;
        QCOMPARE(v2.get<int>(), 20);
    }

    {
        QGlib::Value v2(v);
        QVERIFY(v2.isValid());
        QCOMPARE(v2.type(), QGlib::GetType<int>());
        QCOMPARE(v2.get<int>(), 20);

        v2.set(30);
        QCOMPARE(v.get<int>(), 20);
        QCOMPARE(sv.get<int>(), 20);
        QCOMPARE(v2.get<int>(), 30);

        v2 = sv;
        QCOMPARE(v2.get<int>(), 20);
    }
}

void ValueTest::castTest()
{
    QGlib::Value v(10);
    GValue *gv = v;
    QCOMPARE(G_VALUE_TYPE(gv), G_TYPE_INT);
    QCOMPARE(g_value_get_int(gv), 10);
}

void ValueTest::qdebugTest()
{
    qDebug() << QGlib::Value(10);
    qDebug() << QGlib::Value(QByteArray("Hello world"));
    qDebug() << QGlib::Value(QGlib::ObjectPtr());
}

QTEST_APPLESS_MAIN(ValueTest)

#include "moc_qgsttest.cpp"
#include "valuetest.moc"
<commit_msg>Add more tests for Value.<commit_after>/*
    Copyright (C) 2009  George Kiagiadakis <kiagiadakis.george@gmail.com>
    Copyright (C) 2010 Collabora Ltd.
      @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>

    This library is free software; you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published
    by the Free Software Foundation; either version 2.1 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "qgsttest.h"
#include <QGlib/Value>
#include <QGst/Bin>
#include <QGst/Message>
#include <limits>

class ValueTest : public QGstTest
{
    Q_OBJECT
private Q_SLOTS:
    void intTest();
    void stringTest();
    void stringLiteralTest();
    void constCharTest();
    void enumTest();
    void flagsTest();
    void objectTest();
    void miniObjectTest();
    void capsTest();
    void conversionsTest();
    void copyTest();
    void castTest();
    void qdebugTest();
};

void ValueTest::intTest()
{
    QGlib::Value v(10);
    QVERIFY(v.isValid());
    QCOMPARE(v.type(), QGlib::GetType<int>());
    QCOMPARE(v.get<int>(), 10);
}

void ValueTest::stringTest()
{
    QGlib::Value v;
    QVERIFY(!v.isValid());
    v.init<QString>();
    v.set(QString::fromUtf8("Γειά σου κόσμε"));
    QCOMPARE(v.type(), QGlib::GetType<QString>());
    QByteArray b = v.get<QByteArray>();
    QCOMPARE(QString::fromUtf8(b), QString::fromUtf8("Γειά σου κόσμε"));
    QCOMPARE(v.get<QString>(), QString::fromUtf8("Γειά σου κόσμε"));
}

void ValueTest::stringLiteralTest()
{
    QGlib::Value v("Hello world");
    QCOMPARE(v.type(), QGlib::GetType<QString>());
    QCOMPARE(v.get<QString>(), QString("Hello world"));
}

void ValueTest::constCharTest()
{
    const char *foo = "Hello world";
    QGlib::Value v(foo);
    QCOMPARE(v.type(), QGlib::GetType<QString>());
    QCOMPARE(v.get<QString>(), QString("Hello world"));
}

void ValueTest::enumTest()
{
    QGlib::Value v;
    v.init<QGst::PadDirection>();
    v.set(QGst::PadSink);
    QVERIFY(v.isValid());
    QCOMPARE(v.type(), QGlib::GetType<QGst::PadDirection>());
    QCOMPARE(v.get<QGst::PadDirection>(), QGst::PadSink);
}

void ValueTest::flagsTest()
{
    QGlib::Value v(QGst::PadBlocked | QGst::PadFlushing | QGst::PadFlagLast);
    QCOMPARE(v.type(), QGlib::GetType<QGst::PadFlags>());
    QCOMPARE(v.get<QGst::PadFlags>(), QGst::PadBlocked | QGst::PadFlushing | QGst::PadFlagLast);
}

void ValueTest::objectTest()
{
    QGst::BinPtr bin = QGst::Bin::create();
    QGlib::Value v(bin);
    QCOMPARE(v.type(), QGlib::GetType<QGst::Bin>());
    QCOMPARE(static_cast<GstBin*>(v.get<QGst::BinPtr>()), static_cast<GstBin*>(bin));
}

void ValueTest::miniObjectTest()
{
    QGst::BinPtr bin = QGst::Bin::create();
    QGst::EosMessagePtr msg = QGst::EosMessage::create(bin);
    QGlib::Value v;
    v.init<QGst::Message>();
    v.set(msg);
    QCOMPARE(v.type(), QGlib::GetType<QGst::Message>());
    QCOMPARE(static_cast<GstMessage*>(v.get<QGst::MessagePtr>()), static_cast<GstMessage*>(msg));
}

void ValueTest::capsTest()
{
    QGst::CapsPtr caps = QGst::Caps::createSimple("video/x-raw-rgb");
    QGlib::Value v(caps);
    QCOMPARE(v.type(), QGlib::GetType<QGst::Caps>());
    QCOMPARE(static_cast<GstCaps*>(v.get<QGst::CapsPtr>()), static_cast<GstCaps*>(caps));
    QCOMPARE(v.get<QGst::CapsPtr>()->toString(), QString("video/x-raw-rgb"));
    QCOMPARE(v.get<QString>(), QString("video/x-raw-rgb"));
}

void ValueTest::conversionsTest()
{
    QGlib::Value v;
    v.init<QGst::PadDirection>();

    v.set(1);
    QCOMPARE(v.get<int>(), 1);
    QCOMPARE(v.get<uint>(), 1U);
    QCOMPARE(v.get<QGst::PadDirection>(), QGst::PadSrc);
    QCOMPARE(v.get<QString>(), QString("GST_PAD_SRC"));

    v.set(2U);
    QCOMPARE(v.get<int>(), 2);
    QCOMPARE(v.get<uint>(), 2U);
    QCOMPARE(v.get<QGst::PadDirection>(), QGst::PadSink);
    QCOMPARE(v.get<QString>(), QString("GST_PAD_SINK"));

    v.init<uint>();

    v.set(100); //setting int here, not uint
    QCOMPARE(v.get<int>(), 100);
    QCOMPARE(v.get<uint>(), 100U);
    QCOMPARE(v.get<long>(), 100L);
    QCOMPARE(v.get<ulong>(), 100UL);
    QCOMPARE(v.get<qint64>(), Q_INT64_C(100));
    QCOMPARE(v.get<quint64>(), Q_UINT64_C(100));
    QCOMPARE(v.get<QString>(), QString("100"));

    v.set(-1);
    QCOMPARE(v.get<int>(), -1);
    QCOMPARE(v.get<uint>(), std::numeric_limits<uint>::max());
}

void ValueTest::copyTest()
{
    QGlib::Value v(10);

    QGlib::SharedValue sv(v);
    QVERIFY(sv.isValid());
    QCOMPARE(sv.type(), QGlib::GetType<int>());
    QCOMPARE(sv.get<int>(), 10);

    sv.set(20);
    QCOMPARE(v.get<int>(), 20);

    {
        QGlib::Value v2(sv);
        QVERIFY(v2.isValid());
        QCOMPARE(v2.type(), QGlib::GetType<int>());
        QCOMPARE(v2.get<int>(), 20);

        v2.set(30);
        QCOMPARE(v.get<int>(), 20);
        QCOMPARE(sv.get<int>(), 20);
        QCOMPARE(v2.get<int>(), 30);

        v2 = v;
        QCOMPARE(v2.get<int>(), 20);
    }

    {
        QGlib::Value v2(v);
        QVERIFY(v2.isValid());
        QCOMPARE(v2.type(), QGlib::GetType<int>());
        QCOMPARE(v2.get<int>(), 20);

        v2.set(30);
        QCOMPARE(v.get<int>(), 20);
        QCOMPARE(sv.get<int>(), 20);
        QCOMPARE(v2.get<int>(), 30);

        v2 = sv;
        QCOMPARE(v2.get<int>(), 20);
    }
}

void ValueTest::castTest()
{
    QGlib::Value v(10);
    GValue *gv = v;
    QCOMPARE(G_VALUE_TYPE(gv), G_TYPE_INT);
    QCOMPARE(g_value_get_int(gv), 10);
}

void ValueTest::qdebugTest()
{
    qDebug() << QGlib::Value(10);
    qDebug() << QGlib::Value(QByteArray("Hello world"));
    qDebug() << QGlib::Value(QGlib::ObjectPtr());
}

QTEST_APPLESS_MAIN(ValueTest)

#include "moc_qgsttest.cpp"
#include "valuetest.moc"
<|endoftext|>


<commit_before>#include "TaskbarNotificationAreaIcon.h"

#define ICON_UID	0	//Only one icon allowed

std::unique_ptr<TskbrNtfAreaIcon> TskbrNtfAreaIcon::instance;
UINT TskbrNtfAreaIcon::WmTaskbarCreated=RegisterWindowMessage(L"TaskbarCreated");
std::function<bool(TskbrNtfAreaIcon* sender, WPARAM wParam, LPARAM lParam)> TskbrNtfAreaIcon::OnWmCommand;

TskbrNtfAreaIcon* TskbrNtfAreaIcon::MakeInstance(HINSTANCE hInstance, UINT icon_wm, const wchar_t* icon_tooltip, UINT icon_resid, const wchar_t* icon_class, UINT icon_menuid, UINT default_menuid)
{
	instance.reset(new TskbrNtfAreaIcon(hInstance, icon_wm, icon_tooltip, icon_resid, icon_class, icon_menuid, default_menuid));
	return instance.get();
}

TskbrNtfAreaIcon* TskbrNtfAreaIcon::GetInstance()
{
	if (instance)
		return instance.get();
	else
		return NULL;
}

TskbrNtfAreaIcon::~TskbrNtfAreaIcon()
{
	if (valid) {
		icon_ntfdata.uFlags=0;
		Shell_NotifyIcon(NIM_DELETE, &icon_ntfdata);
	}

	if (icon_ntfdata.hWnd)
		DestroyWindow(icon_ntfdata.hWnd);
}

//Using first version of NOTIFYICONDATA to be compatible with pre-Win2000 OS versions
TskbrNtfAreaIcon::TskbrNtfAreaIcon(HINSTANCE hInstance, UINT icon_wm, const wchar_t* icon_tooltip, UINT icon_resid, const wchar_t* icon_class, UINT icon_menuid, UINT default_menuid):
	valid(false), app_instance(hInstance), default_menuid(default_menuid), icon_ntfdata{
		NOTIFYICONDATA_V1_SIZE, 							//cbSize
		NULL, 												//hWnd (will set it later)
		ICON_UID, 											//uID
		NIF_MESSAGE|NIF_ICON|NIF_TIP, 						//uFlags
		icon_wm,											//uCallbackMessage
		LoadIcon(hInstance, MAKEINTRESOURCE(icon_resid))	//hIcon (szTip and uVersion are initialized with NULLs)
	}
{
	WNDCLASSEX wcex={
		sizeof(WNDCLASSEX),					//cbSize
		CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,	//style
		(WNDPROC)WindowProc,				//lpfnWndProc
		0,									//cbClsExtra
		0,									//cbWndExtra
		hInstance,							//hInstance
		0,									//hIcon
		0,									//hCursor
		0,									//hbrBackground
		MAKEINTRESOURCE(icon_menuid),		//lpszMenuName
		icon_class,							//lpszClassName
		0									//hIconSm
	};

	//Exit only if registration failed not because of already registered class
	//This is done because during a single app run we can try to create taskbar icon several times
	//E.g. first attempt will fail somewhere after class registration, so subsequent attempt will have already registered class at it's disposition
	if (!RegisterClassEx(&wcex)&&GetLastError()!=ERROR_CLASS_ALREADY_EXISTS)
		return;

	if (!(icon_ntfdata.hWnd=CreateWindow(icon_class, L"", WS_POPUP,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, 0, hInstance, 0)))
		return;

	wcsncpy(icon_ntfdata.szTip, icon_tooltip, 63);	//First version of NOTIFYICONDATA only allowes szTip no more than 64 characters in length (including NULL-terminator)

	if (!Shell_NotifyIcon(NIM_ADD, &icon_ntfdata))
		return;

	valid=true;

	icon_menu=GetSubMenu(GetMenu(icon_ntfdata.hWnd), 0);
	SetMenuDefaultItem(icon_menu, default_menuid, FALSE);
}

bool TskbrNtfAreaIcon::IsValid()
{
	return valid;
}

HMENU TskbrNtfAreaIcon::GetIconMenu()
{
	return icon_menu;	//Is set to NULL if instance is not valid
}

void TskbrNtfAreaIcon::ChangeIconTooltip(const wchar_t* icon_tooltip)
{
	if (!valid)
		return;

	wcsncpy(icon_ntfdata.szTip, icon_tooltip, 63);	//First version of NOTIFYICONDATA only allowes szTip no more than 64 characters in length (including NULL-terminator)
	Shell_NotifyIcon(NIM_MODIFY, &icon_ntfdata);
}

void TskbrNtfAreaIcon::ChangeIcon(UINT icon_resid)
{
	if (!valid)
		return;

	icon_ntfdata.hIcon=LoadIcon(app_instance, MAKEINTRESOURCE(icon_resid));
	Shell_NotifyIcon(NIM_MODIFY, &icon_ntfdata);
}

void TskbrNtfAreaIcon::Exit()
{
	PostQuitMessage(0);
}

BOOL TskbrNtfAreaIcon::ModifyIconMenu(UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, LPCWSTR lpNewItem)
{
	if (!valid)
		return FALSE;

	return ModifyMenu(icon_menu, uPosition, uFlags, uIDNewItem, lpNewItem);
}

BOOL TskbrNtfAreaIcon::EnableIconMenuItem(UINT uIDEnableItem, UINT uEnable)
{
	if (!valid)
		return FALSE;

	return EnableMenuItem(icon_menu, uIDEnableItem, uEnable);
}

LRESULT CALLBACK TskbrNtfAreaIcon::WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	if (instance&&instance->valid&&instance->icon_ntfdata.hWnd==hWnd) {
		switch (message) {
			case WM_CREATE:
				return 0;
			case WM_SETTINGCHANGE:		//WM_SETTINGCHANGE with wParam set to SPI_SETWORKAREA signal that icon should be recreated
				if (wParam==SPI_SETWORKAREA)
					Shell_NotifyIcon(NIM_ADD, &instance->icon_ntfdata);
				return 0;
			case WM_COMMAND:
				if (OnWmCommand&&OnWmCommand(instance.get(), wParam, lParam))
					return 0;
				break;	//Let DefWindowProc handle the rest of WM_COMMAND variations if OnWmCommand returned FALSE
			default:
				//Non-const cases goes here
				if (message==instance->icon_ntfdata.uCallbackMessage) {	//Messages that are sent to taskbar icon
					//For the first version of NOTIFYICONDATA lParam (as a whole, not just LOWORD) holds the mouse or keyboard messages and wParam holds icon ID
					if (wParam==ICON_UID) {
						switch (lParam) {
							case WM_RBUTTONUP:
								POINT cur_mouse_pt;
								GetCursorPos(&cur_mouse_pt);
								SetForegroundWindow(hWnd);
								TrackPopupMenu(instance->icon_menu, TPM_LEFTBUTTON|TPM_LEFTALIGN, cur_mouse_pt.x, cur_mouse_pt.y, 0, hWnd, NULL);
								SendMessage(hWnd, WM_NULL, 0, 0);
								return 0;
							case WM_LBUTTONDBLCLK:
								if (OnWmCommand)
									OnWmCommand(instance.get(), instance->default_menuid, 0);
								return 0;
						}
					}
					//Let DefWindowProc handle the rest of uCallbackMessage variations
				} else if (message==WmTaskbarCreated) {	//WM_TASKBARCREATED signal that icon should be recreated
					Shell_NotifyIcon(NIM_ADD, &instance->icon_ntfdata);
					return 0;
				}
				//Let DefWindowProc handle all other messages
		}
	}

	return DefWindowProc(hWnd, message, wParam, lParam);
}
<commit_msg>Frogot to default-initialize var<commit_after>#include "TaskbarNotificationAreaIcon.h"

#define ICON_UID	0	//Only one icon allowed

std::unique_ptr<TskbrNtfAreaIcon> TskbrNtfAreaIcon::instance;
UINT TskbrNtfAreaIcon::WmTaskbarCreated=RegisterWindowMessage(L"TaskbarCreated");
std::function<bool(TskbrNtfAreaIcon* sender, WPARAM wParam, LPARAM lParam)> TskbrNtfAreaIcon::OnWmCommand;

TskbrNtfAreaIcon* TskbrNtfAreaIcon::MakeInstance(HINSTANCE hInstance, UINT icon_wm, const wchar_t* icon_tooltip, UINT icon_resid, const wchar_t* icon_class, UINT icon_menuid, UINT default_menuid)
{
	instance.reset(new TskbrNtfAreaIcon(hInstance, icon_wm, icon_tooltip, icon_resid, icon_class, icon_menuid, default_menuid));
	return instance.get();
}

TskbrNtfAreaIcon* TskbrNtfAreaIcon::GetInstance()
{
	if (instance)
		return instance.get();
	else
		return NULL;
}

TskbrNtfAreaIcon::~TskbrNtfAreaIcon()
{
	if (valid) {
		icon_ntfdata.uFlags=0;
		Shell_NotifyIcon(NIM_DELETE, &icon_ntfdata);
	}

	if (icon_ntfdata.hWnd)
		DestroyWindow(icon_ntfdata.hWnd);
}

//Using first version of NOTIFYICONDATA to be compatible with pre-Win2000 OS versions
TskbrNtfAreaIcon::TskbrNtfAreaIcon(HINSTANCE hInstance, UINT icon_wm, const wchar_t* icon_tooltip, UINT icon_resid, const wchar_t* icon_class, UINT icon_menuid, UINT default_menuid):
	valid(false), app_instance(hInstance), icon_menu(NULL), default_menuid(default_menuid), icon_ntfdata{
		NOTIFYICONDATA_V1_SIZE, 							//cbSize
		NULL, 												//hWnd (will set it later)
		ICON_UID, 											//uID
		NIF_MESSAGE|NIF_ICON|NIF_TIP, 						//uFlags
		icon_wm,											//uCallbackMessage
		LoadIcon(hInstance, MAKEINTRESOURCE(icon_resid))	//hIcon (szTip and uVersion are initialized with NULLs)
	}
{
	WNDCLASSEX wcex={
		sizeof(WNDCLASSEX),					//cbSize
		CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,	//style
		(WNDPROC)WindowProc,				//lpfnWndProc
		0,									//cbClsExtra
		0,									//cbWndExtra
		hInstance,							//hInstance
		0,									//hIcon
		0,									//hCursor
		0,									//hbrBackground
		MAKEINTRESOURCE(icon_menuid),		//lpszMenuName
		icon_class,							//lpszClassName
		0									//hIconSm
	};

	//Exit only if registration failed not because of already registered class
	//This is done because during a single app run we can try to create taskbar icon several times
	//E.g. first attempt will fail somewhere after class registration, so subsequent attempt will have already registered class at it's disposition
	if (!RegisterClassEx(&wcex)&&GetLastError()!=ERROR_CLASS_ALREADY_EXISTS)
		return;

	if (!(icon_ntfdata.hWnd=CreateWindow(icon_class, L"", WS_POPUP,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, 0, hInstance, 0)))
		return;

	wcsncpy(icon_ntfdata.szTip, icon_tooltip, 63);	//First version of NOTIFYICONDATA only allowes szTip no more than 64 characters in length (including NULL-terminator)

	if (!Shell_NotifyIcon(NIM_ADD, &icon_ntfdata))
		return;

	valid=true;

	icon_menu=GetSubMenu(GetMenu(icon_ntfdata.hWnd), 0);
	SetMenuDefaultItem(icon_menu, default_menuid, FALSE);
}

bool TskbrNtfAreaIcon::IsValid()
{
	return valid;
}

HMENU TskbrNtfAreaIcon::GetIconMenu()
{
	return icon_menu;	//Is set to NULL if instance is not valid
}

void TskbrNtfAreaIcon::ChangeIconTooltip(const wchar_t* icon_tooltip)
{
	if (!valid)
		return;

	wcsncpy(icon_ntfdata.szTip, icon_tooltip, 63);	//First version of NOTIFYICONDATA only allowes szTip no more than 64 characters in length (including NULL-terminator)
	Shell_NotifyIcon(NIM_MODIFY, &icon_ntfdata);
}

void TskbrNtfAreaIcon::ChangeIcon(UINT icon_resid)
{
	if (!valid)
		return;

	icon_ntfdata.hIcon=LoadIcon(app_instance, MAKEINTRESOURCE(icon_resid));
	Shell_NotifyIcon(NIM_MODIFY, &icon_ntfdata);
}

void TskbrNtfAreaIcon::Exit()
{
	PostQuitMessage(0);
}

BOOL TskbrNtfAreaIcon::ModifyIconMenu(UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, LPCWSTR lpNewItem)
{
	if (!valid)
		return FALSE;

	return ModifyMenu(icon_menu, uPosition, uFlags, uIDNewItem, lpNewItem);
}

BOOL TskbrNtfAreaIcon::EnableIconMenuItem(UINT uIDEnableItem, UINT uEnable)
{
	if (!valid)
		return FALSE;

	return EnableMenuItem(icon_menu, uIDEnableItem, uEnable);
}

LRESULT CALLBACK TskbrNtfAreaIcon::WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	if (instance&&instance->valid&&instance->icon_ntfdata.hWnd==hWnd) {
		switch (message) {
			case WM_CREATE:
				return 0;
			case WM_SETTINGCHANGE:		//WM_SETTINGCHANGE with wParam set to SPI_SETWORKAREA signal that icon should be recreated
				if (wParam==SPI_SETWORKAREA)
					Shell_NotifyIcon(NIM_ADD, &instance->icon_ntfdata);
				return 0;
			case WM_COMMAND:
				if (OnWmCommand&&OnWmCommand(instance.get(), wParam, lParam))
					return 0;
				break;	//Let DefWindowProc handle the rest of WM_COMMAND variations if OnWmCommand returned FALSE
			default:
				//Non-const cases goes here
				if (message==instance->icon_ntfdata.uCallbackMessage) {	//Messages that are sent to taskbar icon
					//For the first version of NOTIFYICONDATA lParam (as a whole, not just LOWORD) holds the mouse or keyboard messages and wParam holds icon ID
					if (wParam==ICON_UID) {
						switch (lParam) {
							case WM_RBUTTONUP:
								POINT cur_mouse_pt;
								GetCursorPos(&cur_mouse_pt);
								SetForegroundWindow(hWnd);
								TrackPopupMenu(instance->icon_menu, TPM_LEFTBUTTON|TPM_LEFTALIGN, cur_mouse_pt.x, cur_mouse_pt.y, 0, hWnd, NULL);
								SendMessage(hWnd, WM_NULL, 0, 0);
								return 0;
							case WM_LBUTTONDBLCLK:
								if (OnWmCommand)
									OnWmCommand(instance.get(), instance->default_menuid, 0);
								return 0;
						}
					}
					//Let DefWindowProc handle the rest of uCallbackMessage variations
				} else if (message==WmTaskbarCreated) {	//WM_TASKBARCREATED signal that icon should be recreated
					Shell_NotifyIcon(NIM_ADD, &instance->icon_ntfdata);
					return 0;
				}
				//Let DefWindowProc handle all other messages
		}
	}

	return DefWindowProc(hWnd, message, wParam, lParam);
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "Core/Common.h"
#include "Core/Assembler.h"
#include "Archs/MIPS/Mips.h"
#include "Commands/CDirectiveFile.h"
#include "Tests.h"
#include <chrono>

#if defined(_WIN64) || defined(__x86_64__) || defined(__amd64__)
#define ARMIPSNAME "ARMIPS64"
#else
#define ARMIPSNAME "ARMIPS"
#endif

typedef std::chrono::steady_clock Clock;

int wmain(int argc, wchar_t* argv[])
{
	ArmipsArguments parameters;

	auto startTime = Clock::now();

#ifdef ARMIPS_TESTS
	std::wstring name;

	if (argc < 2)
		return !runTests(L"Tests");
	else
		return !runTests(argv[1]);
#endif

	Logger::printLine(L"%s Assembler v%d.%d.%d (%s %s) by Kingcom",
		ARMIPSNAME,ARMIPS_VERSION_MAJOR,ARMIPS_VERSION_MINOR,ARMIPS_VERSION_REVISION,__DATE__,__TIME__);

	StringList arguments = getStringListFromArray(argv,argc);

	if (arguments.size() < 2)
	{
		Logger::printLine(L"Usage: %s file.asm [-temp temp.txt] [-sym symfile.sym]", argv[0]);
		return 1;
	}

	parameters.inputFileName = arguments[1];

	// turn it into an absolute path
	if (isAbsolutePath(parameters.inputFileName) == false)
		parameters.inputFileName = formatString(L"%s/%s",getCurrentDirectory(),arguments[1]);

	if (fileExists(parameters.inputFileName) == false)
	{
		Logger::printLine(L"File %S not found\n",arguments[1]);
		return 1;
	}

	size_t argpos = 2;
	bool printTime = false;
	while (argpos < arguments.size())
	{
		if (arguments[argpos] == L"-temp")
		{
			parameters.tempFileName = arguments[argpos+1];
			argpos += 2;
		} else if (arguments[argpos] == L"-sym")
		{
			parameters.symFileName = arguments[argpos+1];
			parameters.symFileVersion = 1;
			argpos += 2;
		} else if (arguments[argpos] == L"-sym2")
		{
			parameters.symFileName = arguments[argpos+1];
			parameters.symFileVersion = 2;
			argpos += 2;
		} else if (arguments[argpos] == L"-erroronwarning")
		{
			parameters.errorOnWarning = true;
			argpos += 1;
		} else if (arguments[argpos] == L"-equ")
		{
			EquationDefinition def;
			def.name = arguments[argpos + 1];
			def.value = arguments[argpos + 2];
			parameters.equList.push_back(def);
			argpos += 3;
		} else if (arguments[argpos] == L"-strequ")
		{
			EquationDefinition def;
			def.name = arguments[argpos + 1];
			def.value = formatString(L"\"%s\"",arguments[argpos + 2]);
			parameters.equList.push_back(def);
			argpos += 3;
		} else if (arguments[argpos] == L"-time")
		{
			printTime = true;
			argpos += 1;
		} else if (arguments[argpos] == L"-root")
		{
			changeDirectory(arguments[argpos + 1]);
			argpos += 2;
		} else {
			Logger::printLine(L"Invalid parameter %S\n",arguments[argpos]);
			return 1;
		}
	}

	bool result = runArmips(parameters);

	auto endTime = Clock::now();
	auto executionTime = std::chrono::duration_cast<std::chrono::milliseconds>(endTime-startTime);
	if (result == false)
	{
		if (printTime)
			Logger::printLine(L"Aborting. Duration: %.3fs",executionTime.count()/1000.);
		else
			Logger::printLine(L"Aborting.");
		return 1;
	}

	if (printTime)
		Logger::printLine(L"Done. Duration: %.3fs",executionTime.count()/1000.);
	else
		Logger::printLine(L"Done.");
	return 0;
}

#ifndef _WIN32

int main(int argc, char* argv[])
{
	// convert input to wstring
	std::vector<std::wstring> wideStrings;
	for (int i = 0; i < argc; i++)
	{
		std::wstring str = convertUtf8ToWString(argv[i]);
		wideStrings.push_back(str);
	}

	// create argv replacement
	wchar_t** wargv = new wchar_t*[argc];
	for (int i = 0; i < argc; i++)
	{
		wargv[i] = (wchar_t*) wideStrings[i].c_str();
	}

	int result = wmain(argc,wargv);

	delete[] wargv;
	return result;
}

#endif
<commit_msg>Less verbose program output on success, remove timing feature<commit_after>#include "stdafx.h"
#include "Core/Common.h"
#include "Core/Assembler.h"
#include "Archs/MIPS/Mips.h"
#include "Commands/CDirectiveFile.h"
#include "Tests.h"

#if defined(_WIN64) || defined(__x86_64__) || defined(__amd64__)
#define ARMIPSNAME "ARMIPS64"
#else
#define ARMIPSNAME "ARMIPS"
#endif

int wmain(int argc, wchar_t* argv[])
{
	ArmipsArguments parameters;

#ifdef ARMIPS_TESTS
	std::wstring name;

	if (argc < 2)
		return !runTests(L"Tests");
	else
		return !runTests(argv[1]);
#endif

	StringList arguments = getStringListFromArray(argv,argc);

	if (arguments.size() < 2)
	{
		Logger::printLine(L"%s Assembler v%d.%d.%d (%s %s) by Kingcom",
			ARMIPSNAME,ARMIPS_VERSION_MAJOR,ARMIPS_VERSION_MINOR,ARMIPS_VERSION_REVISION,__DATE__,__TIME__);
		Logger::printLine(L"Usage: %s file.asm [-temp temp.txt] [-sym symfile.sym]", argv[0]);
		return 1;
	}

	parameters.inputFileName = arguments[1];

	// turn it into an absolute path
	if (isAbsolutePath(parameters.inputFileName) == false)
		parameters.inputFileName = formatString(L"%s/%s",getCurrentDirectory(),arguments[1]);

	if (fileExists(parameters.inputFileName) == false)
	{
		Logger::printLine(L"File %S not found\n",arguments[1]);
		return 1;
	}

	size_t argpos = 2;
	bool printTime = false;
	while (argpos < arguments.size())
	{
		if (arguments[argpos] == L"-temp")
		{
			parameters.tempFileName = arguments[argpos+1];
			argpos += 2;
		} else if (arguments[argpos] == L"-sym")
		{
			parameters.symFileName = arguments[argpos+1];
			parameters.symFileVersion = 1;
			argpos += 2;
		} else if (arguments[argpos] == L"-sym2")
		{
			parameters.symFileName = arguments[argpos+1];
			parameters.symFileVersion = 2;
			argpos += 2;
		} else if (arguments[argpos] == L"-erroronwarning")
		{
			parameters.errorOnWarning = true;
			argpos += 1;
		} else if (arguments[argpos] == L"-equ")
		{
			EquationDefinition def;
			def.name = arguments[argpos + 1];
			def.value = arguments[argpos + 2];
			parameters.equList.push_back(def);
			argpos += 3;
		} else if (arguments[argpos] == L"-strequ")
		{
			EquationDefinition def;
			def.name = arguments[argpos + 1];
			def.value = formatString(L"\"%s\"",arguments[argpos + 2]);
			parameters.equList.push_back(def);
			argpos += 3;
		} else if (arguments[argpos] == L"-root")
		{
			changeDirectory(arguments[argpos + 1]);
			argpos += 2;
		} else {
			Logger::printLine(L"Invalid parameter %S\n",arguments[argpos]);
			return 1;
		}
	}

	bool result = runArmips(parameters);

	if (result == false)
	{
		Logger::printLine(L"Aborting.");
		return 1;
	}

	return 0;
}

#ifndef _WIN32

int main(int argc, char* argv[])
{
	// convert input to wstring
	std::vector<std::wstring> wideStrings;
	for (int i = 0; i < argc; i++)
	{
		std::wstring str = convertUtf8ToWString(argv[i]);
		wideStrings.push_back(str);
	}

	// create argv replacement
	wchar_t** wargv = new wchar_t*[argc];
	for (int i = 0; i < argc; i++)
	{
		wargv[i] = (wchar_t*) wideStrings[i].c_str();
	}

	int result = wmain(argc,wargv);

	delete[] wargv;
	return result;
}

#endif
<|endoftext|>


<commit_before><commit_msg>Fixed Test_UserInput function<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2016 Emaad Ahmed Manzoor
 * License: Apache License, Version 2.0
 * http://www3.cs.stonybrook.edu/~emanzoor/streamspot/
 */

#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <deque>
#include <iostream>
#include <queue>
#include <random>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "cluster.h"
#include "docopt.h"
#include "graph.h"
#include "hash.h"
#include "io.h"
#include "param.h"
#include "simhash.h"
#include "streamhash.h"

using namespace std;

static const char USAGE[] =
R"(StreamSpot.

    Usage:
      streamspot --edges=<edge file>
                 --feature=<feature>

      streamspot (-h | --help)

    Options:
      -h, --help                              Show this screen.
      --edges=<edge file>                     Incoming stream of edges.
      --feature=<feature>                     Feature to compute for each graph.
)";

int main(int argc, char *argv[]) {
  std::cout.precision(3);
  map<string, docopt::value> args = docopt::docopt(USAGE, { argv + 1, argv + argc });

  string edge_file(args["--edges"].asString());
  string feature(args["--feature"].asString());

  cout << "StreamSpot (";
  cout << "Edges=" << edge_file << " ";
  cout << "Feature=" << feature << "";
  cout << ")" << endl;

  unordered_set<uint32_t> train_gids;
  for (uint32_t i = 0; i < 600; i++) {
    train_gids.insert(i);
  }

  unordered_set<uint32_t> scenarios;
  for (uint32_t i = 0; i < 6; i++) {
    scenarios.insert(i);
  }

  uint32_t num_graphs;
  uint32_t num_test_edges;
  vector<edge> train_edges;
  unordered_map<uint32_t,vector<edge>> test_edges;
  tie(num_graphs, train_edges, test_edges, num_test_edges) =
    read_edges(edge_file, train_gids, scenarios);

  if (num_graphs == 0) {
    cout << "0 graphs in file" << endl;
    exit(-1);
  }

  vector<graph> graphs(num_graphs);
  cout << "Constructing " << num_graphs << " graphs..." << endl;
  for (auto& e : train_edges) {
    update_graphs(e, graphs);
  }

  // feature computation
  if (feature.compare("nverts") == 0) {
    unordered_map<uint32_t,uint32_t> number_of_nodes;
    for (uint32_t i = 0; i < num_graphs; i++) {
      number_of_nodes[i] = get_number_of_nodes(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << number_of_nodes[i] << endl;
    }
  } else if (feature.compare("nedges") == 0) {
    unordered_map<uint32_t,uint32_t> number_of_edges;
    for (uint32_t i = 0; i < num_graphs; i++) {
      number_of_edges[i] = get_number_of_edges(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << number_of_edges[i] << endl;
    }
  } else if (feature.compare("density") == 0) {
    unordered_map<uint32_t,float> d;
    for (uint32_t i = 0; i < num_graphs; i++) {
      d[i] = get_density(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << d[i] << endl;
    }
  } else if (feature.compare("diameter") == 0) {
    unordered_map<uint32_t,uint32_t> diameter;
    for (uint32_t i = 0; i < num_graphs; i++) {
      diameter[i] = get_diameter(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << diameter[i] << endl;
    }
  } else if (feature.compare("avg-path-length") == 0) {
    unordered_map<uint32_t,float> avg;
    for (uint32_t i = 0; i < num_graphs; i++) {
      avg[i] = get_average_path_length(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << avg[i] << endl;
    }
  } else if (feature.compare("effective-diameter") == 0) {
    unordered_map<uint32_t,float> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_effective_diameter(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else if (feature.compare("avg-degree") == 0) {
    unordered_map<uint32_t,float> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_average_degree(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else if (feature.compare("max-degree") == 0) {
    unordered_map<uint32_t,uint32_t> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_max_degree(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else if (feature.compare("90pct-degree") == 0) {
    unordered_map<uint32_t,float> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_90pct_degree(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else if (feature.compare("avg-distinct-degree") == 0) {
    unordered_map<uint32_t,float> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_average_distinct_degree(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else if (feature.compare("max-distinct-degree") == 0) {
    unordered_map<uint32_t,uint32_t> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_max_distinct_degree(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else if (feature.compare("90pct-distinct-degree") == 0) {
    unordered_map<uint32_t,float> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_90pct_distinct_degree(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else if (feature.compare("avg-eccentricity") == 0) {
    unordered_map<uint32_t,float> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_average_eccentricity(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else if (feature.compare("max-eccentricity") == 0) {
    unordered_map<uint32_t,uint32_t> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_max_eccentricity(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else if (feature.compare("radius") == 0) {
    unordered_map<uint32_t,uint32_t> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_radius(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else if (feature.compare("90pct-eccentricity") == 0) {
    unordered_map<uint32_t,float> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_90pct_eccentricity(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else {
    cout << "Unknown feature: " << feature << ". Available features:" << endl;
    cout << "\tnverts" << endl;
    cout << "\tnedges" << endl;
    cout << "\tdensity" << endl;
    cout << "\tdiameter" << endl;
    cout << "\tavg-path-length" << endl;
    cout << "\teffective-diameter" << endl;
    cout << "\tavg-degree" << endl;
    cout << "\tmax-degree" << endl;
    cout << "\t90pct-degree" << endl;
    cout << "\tavg-distinct-degree" << endl;
    cout << "\tmax-distinct-degree" << endl;
    cout << "\t90pct-distinct-degree" << endl;
    cout << "\tavg-eccentricity" << endl;
    cout << "\tmax-eccentricity" << endl;
    cout << "\tradius" << endl;
    cout << "\t90pct-eccentricity" << endl;
    exit(-1);
  }

  return 0;
}
<commit_msg>path len, degree, ecc distributions<commit_after>/*
 * Copyright 2016 Emaad Ahmed Manzoor
 * License: Apache License, Version 2.0
 * http://www3.cs.stonybrook.edu/~emanzoor/streamspot/
 */

#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <deque>
#include <iostream>
#include <queue>
#include <random>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "cluster.h"
#include "docopt.h"
#include "graph.h"
#include "hash.h"
#include "io.h"
#include "param.h"
#include "simhash.h"
#include "streamhash.h"

using namespace std;

static const char USAGE[] =
R"(StreamSpot.

    Usage:
      streamspot --edges=<edge file>
                 --feature=<feature>

      streamspot (-h | --help)

    Options:
      -h, --help                              Show this screen.
      --edges=<edge file>                     Incoming stream of edges.
      --feature=<feature>                     Feature to compute for each graph.
)";

int main(int argc, char *argv[]) {
  std::cout.precision(3);
  map<string, docopt::value> args = docopt::docopt(USAGE, { argv + 1, argv + argc });

  string edge_file(args["--edges"].asString());
  string feature(args["--feature"].asString());

  cout << "StreamSpot (";
  cout << "Edges=" << edge_file << " ";
  cout << "Feature=" << feature << "";
  cout << ")" << endl;

  unordered_set<uint32_t> train_gids;
  for (uint32_t i = 0; i < 600; i++) {
    train_gids.insert(i);
  }

  unordered_set<uint32_t> scenarios;
  for (uint32_t i = 0; i < 6; i++) {
    scenarios.insert(i);
  }

  uint32_t num_graphs;
  uint32_t num_test_edges;
  vector<edge> train_edges;
  unordered_map<uint32_t,vector<edge>> test_edges;
  tie(num_graphs, train_edges, test_edges, num_test_edges) =
    read_edges(edge_file, train_gids, scenarios);

  if (num_graphs == 0) {
    cout << "0 graphs in file" << endl;
    exit(-1);
  }

  vector<graph> graphs(num_graphs);
  cout << "Constructing " << num_graphs << " graphs..." << endl;
  for (auto& e : train_edges) {
    update_graphs(e, graphs);
  }

  // feature computation
  if (feature.compare("nverts") == 0) {
    unordered_map<uint32_t,uint32_t> number_of_nodes;
    for (uint32_t i = 0; i < num_graphs; i++) {
      number_of_nodes[i] = get_number_of_nodes(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << number_of_nodes[i] << endl;
    }
  } else if (feature.compare("nedges") == 0) {
    unordered_map<uint32_t,uint32_t> number_of_edges;
    for (uint32_t i = 0; i < num_graphs; i++) {
      number_of_edges[i] = get_number_of_edges(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << number_of_edges[i] << endl;
    }
  } else if (feature.compare("density") == 0) {
    unordered_map<uint32_t,float> d;
    for (uint32_t i = 0; i < num_graphs; i++) {
      d[i] = get_density(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << d[i] << endl;
    }
  } else if (feature.compare("diameter") == 0) {
    unordered_map<uint32_t,uint32_t> diameter;
    for (uint32_t i = 0; i < num_graphs; i++) {
      diameter[i] = get_diameter(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << diameter[i] << endl;
    }
  } else if (feature.compare("avg-path-length") == 0) {
    unordered_map<uint32_t,float> avg;
    for (uint32_t i = 0; i < num_graphs; i++) {
      avg[i] = get_average_path_length(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << avg[i] << endl;
    }
  } else if (feature.compare("path-length-distribution") == 0) {
    unordered_map<uint32_t,vector<uint32_t>> d;
    for (uint32_t i = 0; i < num_graphs; i++) {
      d[i] = get_path_lengths(graphs[i]);
      cout << i << "\t";
      for (uint32_t j = 0; j < d[i].size(); j++) {
        cout << fixed << static_cast<int>(d[i][j]) << "\t";
      }
      cout << endl;
    }
  } else if (feature.compare("effective-diameter") == 0) {
    unordered_map<uint32_t,float> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_effective_diameter(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else if (feature.compare("avg-degree") == 0) {
    unordered_map<uint32_t,float> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_average_degree(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else if (feature.compare("degree-distribution") == 0) {
    unordered_map<uint32_t,vector<uint32_t>> d;
    for (uint32_t i = 0; i < num_graphs; i++) {
      d[i] = get_degrees(graphs[i]);
      cout << i << "\t";
      for (uint32_t j = 0; j < d[i].size(); j++) {
        cout << fixed << static_cast<int>(d[i][j]) << "\t";
      }
      cout << endl;
    }
  } else if (feature.compare("max-degree") == 0) {
    unordered_map<uint32_t,uint32_t> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_max_degree(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else if (feature.compare("90pct-degree") == 0) {
    unordered_map<uint32_t,float> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_90pct_degree(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else if (feature.compare("avg-distinct-degree") == 0) {
    unordered_map<uint32_t,float> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_average_distinct_degree(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else if (feature.compare("max-distinct-degree") == 0) {
    unordered_map<uint32_t,uint32_t> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_max_distinct_degree(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else if (feature.compare("90pct-distinct-degree") == 0) {
    unordered_map<uint32_t,float> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_90pct_distinct_degree(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else if (feature.compare("avg-eccentricity") == 0) {
    unordered_map<uint32_t,float> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_average_eccentricity(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else if (feature.compare("eccentricity-distribution") == 0) {
    unordered_map<uint32_t,vector<uint32_t>> d;
    for (uint32_t i = 0; i < num_graphs; i++) {
      d[i] = get_eccentricities(graphs[i]);
      cout << i << "\t";
      for (uint32_t j = 0; j < d[i].size(); j++) {
        cout << fixed << static_cast<int>(d[i][j]) << "\t";
      }
      cout << endl;
    }
  } else if (feature.compare("max-eccentricity") == 0) {
    unordered_map<uint32_t,uint32_t> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_max_eccentricity(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else if (feature.compare("radius") == 0) {
    unordered_map<uint32_t,uint32_t> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_radius(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else if (feature.compare("90pct-eccentricity") == 0) {
    unordered_map<uint32_t,float> ed;
    for (uint32_t i = 0; i < num_graphs; i++) {
      ed[i] = get_90pct_eccentricity(graphs[i]);
    }
    for (uint32_t i = 0; i < num_graphs; i++) {
      cout << i << "\t" << fixed << ed[i] << endl;
    }
  } else {
    cout << "Unknown feature: " << feature << ". Available features:" << endl;
    cout << "\tnverts" << endl;
    cout << "\tnedges" << endl;
    cout << "\tdensity" << endl;
    cout << "\tdiameter" << endl;
    cout << "\tavg-path-length" << endl;
    cout << "\tpath-length-distribution" << endl;
    cout << "\teffective-diameter" << endl;
    cout << "\tavg-degree" << endl;
    cout << "\tdegree-distribution" << endl;
    cout << "\tmax-degree" << endl;
    cout << "\t90pct-degree" << endl;
    cout << "\tavg-distinct-degree" << endl;
    cout << "\tmax-distinct-degree" << endl;
    cout << "\t90pct-distinct-degree" << endl;
    cout << "\tavg-eccentricity" << endl;
    cout << "\teccentricity-distribution" << endl;
    cout << "\tmax-eccentricity" << endl;
    cout << "\tradius" << endl;
    cout << "\t90pct-eccentricity" << endl;
    exit(-1);
  }

  return 0;
}
<|endoftext|>