<commit_before>#include <iostream>
#include <client/dbclient.h>

extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

#if !defined(LUA_VERSION_NUM) || (LUA_VERSION_NUM < 501)
#include <compat-5.1.h>
#endif
};

#include "common.h"

using namespace mongo;

void push_bsontype_table(lua_State* L, mongo::BSONType bsontype);
extern const char *bson_name(int type);
extern void lua_to_bson(lua_State *L, int stackpos, BSONObj &obj);
extern void bson_to_lua(lua_State *L, const BSONObj &obj);

static int bson_type_Date(lua_State *L) {
    push_bsontype_table(L, mongo::Date);
    lua_pushvalue(L, 1);
    lua_rawseti(L, -2, 1); // t[1] = function arg #1
    return 1;
}

static int bson_type_Timestamp(lua_State*L) {
    push_bsontype_table(L, mongo::Timestamp);
    // no arg
    return 1;
}

static int bson_type_RegEx(lua_State *L) {
    push_bsontype_table(L, mongo::RegEx);
    lua_pushvalue(L, 1);
    lua_rawseti(L, -2, 1); // t[1] = function arg #1
    lua_pushvalue(L, 2);
    lua_rawseti(L, -2, 2); // set t[2] = function arg #2
    return 1;
}

static int bson_type_NumberInt(lua_State *L) {
    push_bsontype_table(L, mongo::NumberInt);
    lua_pushvalue(L, 1);
    lua_rawseti(L, -2, 1); // t[1] = function arg #1
    return 1;
}

static int bson_type_NumberLong(lua_State *L) {
    push_bsontype_table(L, mongo::NumberLong);
    lua_pushvalue(L, 1);
    lua_rawseti(L, -2, 1); // t[1] = function arg #1
    return 1;
}

static int bson_type_Symbol(lua_State *L) {
    push_bsontype_table(L, mongo::Symbol);
    lua_pushvalue(L, 1);
    lua_rawseti(L, -2, 1); // t[1] = function arg #1
    return 1;
}

static int bson_type_ObjectID(lua_State *L) {
    push_bsontype_table(L, mongo::jstOID);
    lua_pushvalue(L, 1);
    lua_rawseti(L, -2, 1); // t[1] = function arg #1
    return 1;
}

static int bson_type_NULL(lua_State *L) {
    push_bsontype_table(L, mongo::jstNULL);
    // no arg
    return 1;
}

static int integer_value(lua_State *L) {
    int n = lua_gettop(L);
    int returncount = 1;

    lua_rawgeti(L, 1, 1);

    if (n > 1) {
        lua_pushinteger(L, luaL_checkint(L, 2));
        lua_rawseti(L, 1, 1);
        returncount = 0;
    } else {
        lua_pushinteger(L, luaL_checkint(L, -1));
    }

    return returncount;
}

static int number_value(lua_State *L) {
    int n = lua_gettop(L);
    int returncount = 1;

    lua_rawgeti(L, 1, 1);

    if (n > 1) {
        lua_pushnumber(L, luaL_checknumber(L, 2));
        lua_rawseti(L, 1, 1);
        returncount = 0;
    } else {
        lua_pushnumber(L, luaL_checknumber(L, -1));
    }

    return returncount;
}

static int string_value(lua_State *L) {
    int n = lua_gettop(L);
    int returncount = 1;

    lua_rawgeti(L, 1, 1);

    if (n > 1) {
        lua_pushstring(L, luaL_checkstring(L, 2));
        lua_rawseti(L, 1, 1);
        returncount = 0;
    } else {
        lua_pushstring(L, luaL_checkstring(L, -1));
    }

    return returncount;
}

static int null_value(lua_State *L) {
    lua_pushnil(L);

    return 1;
}

static int stringpair_value(lua_State *L) {
    int n = lua_gettop(L);
    int returncount = 2;

    lua_rawgeti(L, 1, 1);
    lua_rawgeti(L, 1, 2);

    if (n > 1) {
        lua_pushstring(L, luaL_checkstring(L, 2));
        lua_rawseti(L, 1, 1);
        lua_pushstring(L, luaL_checkstring(L, 3));
        lua_rawseti(L, 1, 2);
        returncount = 0;
    } else {
        lua_pushstring(L, luaL_checkstring(L, -2));
        lua_pushstring(L, luaL_checkstring(L, -2));
    }

    return returncount;
}

static int generic_tostring(lua_State *L) {
    lua_rawgeti(L, 1, 1);

    lua_pushstring(L, luaL_optstring(L, -1, "nil"));

    return 1;
}

static int longlong_tostring(lua_State *L) {
    lua_rawgeti(L, 1, 1);
    lua_Number num = lua_tonumber(L, -1);

    char numstr[64];
    int len = snprintf(numstr, 64, "%.f", num);

    lua_pushlstring(L, numstr, len);

    return 1;
}

static int date_tostring(lua_State *L) {
    char datestr[64];

    lua_rawgeti(L, 1, 1);

    time_t t = (time_t)(lua_tonumber(L, -1)/1000);

#if defined(_WIN32)
    ctime_s(datestr, 64, &t);
#else
    ctime_r(&t,datestr);
#endif

    datestr[24] = 0; // don't want the \n

    lua_pushstring(L, datestr);

    return 1;
}

static int regex_tostring(lua_State *L) {
    lua_rawgeti(L, 1, 1);
    lua_rawgeti(L, 1, 2);

    lua_pushfstring(L, "/%s/%s", lua_tostring(L, -2),  lua_tostring(L, -1));

    return 1;
}

static int null_tostring(lua_State *L) {
    lua_pushstring(L, "NULL");

    return 1;
}

// TODO:
//    all of this should be in Lua so it can get JIT wins
//    bind the bson typeids
//    each type could have its cached metatable (from registry)

// all these types are represented as tables
// the metatable entry __bsontype dictates the type
// the t[1] represents the object itself, with some types using other fields

void push_bsontype_table(lua_State* L, mongo::BSONType bsontype) {
    lua_newtable(L);
    lua_newtable(L);

    lua_pushstring(L, "__bsontype");
    lua_pushinteger(L, bsontype);
    lua_settable(L, -3);

    lua_pushstring(L, "__call");
    switch(bsontype) {
        case mongo::NumberInt:
            lua_pushcfunction(L, integer_value);
            break;
        case mongo::NumberLong:
        case mongo::Date:
        case mongo::Timestamp:
            lua_pushcfunction(L, number_value);
            break;
        case mongo::Symbol:
        case mongo::jstOID:
            lua_pushcfunction(L, string_value);
            break;
        case mongo::RegEx:
            lua_pushcfunction(L, stringpair_value);
            break;
        case mongo::jstNULL:
            lua_pushcfunction(L, null_value);
            break;
    }
    lua_settable(L, -3);

    lua_pushstring(L, "__tostring");
    switch(bsontype) {
        case mongo::NumberInt:
        case mongo::Symbol:
        case mongo::jstOID:
            lua_pushcfunction(L, generic_tostring);
            break;
        case mongo::Timestamp:
        case mongo::NumberLong:
            lua_pushcfunction(L, longlong_tostring);
            break;
        case mongo::Date:
            lua_pushcfunction(L, date_tostring);
            break;
        case mongo::RegEx:
            lua_pushcfunction(L, regex_tostring);
            break;
        case mongo::jstNULL:
            lua_pushcfunction(L, null_tostring);
            break;
    }
    lua_settable(L, -3);

    lua_setmetatable(L, -2);
}

/*
 * typename = mongo.type(obj)
 */
static int bson_type_name(lua_State *L) {
    if (lua_istable(L, 1)) {
        int bsontype_found = luaL_getmetafield(L, 1, "__bsontype");

        if (bsontype_found) {
            int bson_type = lua_tointeger(L, -1);
            lua_pop(L, 1);

            lua_pushfstring(L, "%s.%s", LUAMONGO_ROOT, bson_name(bson_type));
        } else {
            lua_pushstring(L, luaL_typename(L, 1));
        }
    } else {
        lua_pushstring(L, luaL_typename(L, 1));
    }

    return 1;
}

/*
 * num = mongo.tonumber(obj)
 */
static int bson_tonumber(lua_State *L) {
    int base = luaL_optint(L, 2, 10);
    if (base == 10) {  /* standard conversion */
        luaL_checkany(L, 1);
        if (lua_isnumber(L, 1)) {
            lua_pushnumber(L, lua_tonumber(L, 1));
            return 1;
        } else if (lua_istable(L, 1)) {
            int bsontype_found = luaL_getmetafield(L, 1, "__bsontype");

            if (bsontype_found) {
                lua_rawgeti(L, 1, 1);

                if (lua_isnumber(L, -1)) {
                    lua_pushnumber(L, lua_tonumber(L, -1));
                    return 1;
                }

                lua_pop(L, 1);
            }
        }
    } else {
        const char *s1 = luaL_checkstring(L, 1);
        char *s2;
        unsigned long n;
        luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
        n = strtoul(s1, &s2, base);
        if (s1 != s2) {  /* at least one valid digit? */
            while (isspace((unsigned char)(*s2))) s2++;  /* skip trailing spaces */
            if (*s2 == '\0') {  /* no invalid trailing characters? */
                lua_pushnumber(L, (lua_Number)n);
                return 1;
            }
        }
    }

    lua_pushnil(L);  /* else not a number */
    return 1;
}

static int bson_tojson(lua_State *L) {
    int resultcount = 1;
    BSONObj obj;

    if (lua_istable(L, 1)) {
        lua_to_bson(L, 1, obj);

        lua_pushstring(L, obj.toString().c_str());
    } else {
        lua_pushnil(L);
        lua_pushfstring(L, "Argument is not a table");
        resultcount = 2;
    }

    return resultcount;
}

static int bson_fromjson(lua_State *L) {
    const char *json = luaL_checkstring(L, 1);
    int resultcount = 1;
    BSONObj obj;

    try {
        bson_to_lua(L, fromjson(json));
    } catch (std::exception &e) {
        lua_pushnil(L);
        lua_pushfstring(L, "Error parsing JSON: %s", e.what());
        resultcount = 2;
    }

    return resultcount;
}

int mongo_bsontypes_register(lua_State *L) {
    static const luaL_Reg bsontype_methods[] = {
        {"Date", bson_type_Date},
        {"Timestamp", bson_type_Timestamp},
        {"RegEx", bson_type_RegEx},
        {"NumberInt", bson_type_NumberInt},
        {"NumberLong", bson_type_NumberLong},
        {"Symbol", bson_type_Symbol},
        {"ObjectId", bson_type_ObjectID},
        {"NULL", bson_type_NULL},

        // Utils
        {"type", bson_type_name},
        {"tonumber", bson_tonumber},
        {"tojson", bson_tojson},
        {"fromjson", bson_fromjson},
        {NULL, NULL}
    };

    luaL_register(L, LUAMONGO_ROOT, bsontype_methods);

    return 1;
}

<commit_msg>mongo.ObjectID(): Initialize with generated OID if no input was given.<commit_after>#include <iostream>
#include <client/dbclient.h>

extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

#if !defined(LUA_VERSION_NUM) || (LUA_VERSION_NUM < 501)
#include <compat-5.1.h>
#endif
};

#include "common.h"

using namespace mongo;

void push_bsontype_table(lua_State* L, mongo::BSONType bsontype);
extern const char *bson_name(int type);
extern void lua_to_bson(lua_State *L, int stackpos, BSONObj &obj);
extern void bson_to_lua(lua_State *L, const BSONObj &obj);

static int bson_type_Date(lua_State *L) {
    push_bsontype_table(L, mongo::Date);
    lua_pushvalue(L, 1);
    lua_rawseti(L, -2, 1); // t[1] = function arg #1
    return 1;
}

static int bson_type_Timestamp(lua_State*L) {
    push_bsontype_table(L, mongo::Timestamp);
    // no arg
    return 1;
}

static int bson_type_RegEx(lua_State *L) {
    push_bsontype_table(L, mongo::RegEx);
    lua_pushvalue(L, 1);
    lua_rawseti(L, -2, 1); // t[1] = function arg #1
    lua_pushvalue(L, 2);
    lua_rawseti(L, -2, 2); // set t[2] = function arg #2
    return 1;
}

static int bson_type_NumberInt(lua_State *L) {
    push_bsontype_table(L, mongo::NumberInt);
    lua_pushvalue(L, 1);
    lua_rawseti(L, -2, 1); // t[1] = function arg #1
    return 1;
}

static int bson_type_NumberLong(lua_State *L) {
    push_bsontype_table(L, mongo::NumberLong);
    lua_pushvalue(L, 1);
    lua_rawseti(L, -2, 1); // t[1] = function arg #1
    return 1;
}

static int bson_type_Symbol(lua_State *L) {
    push_bsontype_table(L, mongo::Symbol);
    lua_pushvalue(L, 1);
    lua_rawseti(L, -2, 1); // t[1] = function arg #1
    return 1;
}

static int bson_type_ObjectID(lua_State *L) {
    if(lua_gettop(L) == 0)
        lua_pushstring(L, mongo::OID::gen().toString().data());
    push_bsontype_table(L, mongo::jstOID);
    lua_pushvalue(L, 1);
    lua_rawseti(L, -2, 1); // t[1] = function arg #1
    return 1;
}

static int bson_type_NULL(lua_State *L) {
    push_bsontype_table(L, mongo::jstNULL);
    // no arg
    return 1;
}

static int integer_value(lua_State *L) {
    int n = lua_gettop(L);
    int returncount = 1;

    lua_rawgeti(L, 1, 1);

    if (n > 1) {
        lua_pushinteger(L, luaL_checkint(L, 2));
        lua_rawseti(L, 1, 1);
        returncount = 0;
    } else {
        lua_pushinteger(L, luaL_checkint(L, -1));
    }

    return returncount;
}

static int number_value(lua_State *L) {
    int n = lua_gettop(L);
    int returncount = 1;

    lua_rawgeti(L, 1, 1);

    if (n > 1) {
        lua_pushnumber(L, luaL_checknumber(L, 2));
        lua_rawseti(L, 1, 1);
        returncount = 0;
    } else {
        lua_pushnumber(L, luaL_checknumber(L, -1));
    }

    return returncount;
}

static int string_value(lua_State *L) {
    int n = lua_gettop(L);
    int returncount = 1;

    lua_rawgeti(L, 1, 1);

    if (n > 1) {
        lua_pushstring(L, luaL_checkstring(L, 2));
        lua_rawseti(L, 1, 1);
        returncount = 0;
    } else {
        lua_pushstring(L, luaL_checkstring(L, -1));
    }

    return returncount;
}

static int null_value(lua_State *L) {
    lua_pushnil(L);

    return 1;
}

static int stringpair_value(lua_State *L) {
    int n = lua_gettop(L);
    int returncount = 2;

    lua_rawgeti(L, 1, 1);
    lua_rawgeti(L, 1, 2);

    if (n > 1) {
        lua_pushstring(L, luaL_checkstring(L, 2));
        lua_rawseti(L, 1, 1);
        lua_pushstring(L, luaL_checkstring(L, 3));
        lua_rawseti(L, 1, 2);
        returncount = 0;
    } else {
        lua_pushstring(L, luaL_checkstring(L, -2));
        lua_pushstring(L, luaL_checkstring(L, -2));
    }

    return returncount;
}

static int generic_tostring(lua_State *L) {
    lua_rawgeti(L, 1, 1);

    lua_pushstring(L, luaL_optstring(L, -1, "nil"));

    return 1;
}

static int longlong_tostring(lua_State *L) {
    lua_rawgeti(L, 1, 1);
    lua_Number num = lua_tonumber(L, -1);

    char numstr[64];
    int len = snprintf(numstr, 64, "%.f", num);

    lua_pushlstring(L, numstr, len);

    return 1;
}

static int date_tostring(lua_State *L) {
    char datestr[64];

    lua_rawgeti(L, 1, 1);

    time_t t = (time_t)(lua_tonumber(L, -1)/1000);

#if defined(_WIN32)
    ctime_s(datestr, 64, &t);
#else
    ctime_r(&t,datestr);
#endif

    datestr[24] = 0; // don't want the \n

    lua_pushstring(L, datestr);

    return 1;
}

static int regex_tostring(lua_State *L) {
    lua_rawgeti(L, 1, 1);
    lua_rawgeti(L, 1, 2);

    lua_pushfstring(L, "/%s/%s", lua_tostring(L, -2),  lua_tostring(L, -1));

    return 1;
}

static int null_tostring(lua_State *L) {
    lua_pushstring(L, "NULL");

    return 1;
}

// TODO:
//    all of this should be in Lua so it can get JIT wins
//    bind the bson typeids
//    each type could have its cached metatable (from registry)

// all these types are represented as tables
// the metatable entry __bsontype dictates the type
// the t[1] represents the object itself, with some types using other fields

void push_bsontype_table(lua_State* L, mongo::BSONType bsontype) {
    lua_newtable(L);
    lua_newtable(L);

    lua_pushstring(L, "__bsontype");
    lua_pushinteger(L, bsontype);
    lua_settable(L, -3);

    lua_pushstring(L, "__call");
    switch(bsontype) {
        case mongo::NumberInt:
            lua_pushcfunction(L, integer_value);
            break;
        case mongo::NumberLong:
        case mongo::Date:
        case mongo::Timestamp:
            lua_pushcfunction(L, number_value);
            break;
        case mongo::Symbol:
        case mongo::jstOID:
            lua_pushcfunction(L, string_value);
            break;
        case mongo::RegEx:
            lua_pushcfunction(L, stringpair_value);
            break;
        case mongo::jstNULL:
            lua_pushcfunction(L, null_value);
            break;
    }
    lua_settable(L, -3);

    lua_pushstring(L, "__tostring");
    switch(bsontype) {
        case mongo::NumberInt:
        case mongo::Symbol:
        case mongo::jstOID:
            lua_pushcfunction(L, generic_tostring);
            break;
        case mongo::Timestamp:
        case mongo::NumberLong:
            lua_pushcfunction(L, longlong_tostring);
            break;
        case mongo::Date:
            lua_pushcfunction(L, date_tostring);
            break;
        case mongo::RegEx:
            lua_pushcfunction(L, regex_tostring);
            break;
        case mongo::jstNULL:
            lua_pushcfunction(L, null_tostring);
            break;
    }
    lua_settable(L, -3);

    lua_setmetatable(L, -2);
}

/*
 * typename = mongo.type(obj)
 */
static int bson_type_name(lua_State *L) {
    if (lua_istable(L, 1)) {
        int bsontype_found = luaL_getmetafield(L, 1, "__bsontype");

        if (bsontype_found) {
            int bson_type = lua_tointeger(L, -1);
            lua_pop(L, 1);

            lua_pushfstring(L, "%s.%s", LUAMONGO_ROOT, bson_name(bson_type));
        } else {
            lua_pushstring(L, luaL_typename(L, 1));
        }
    } else {
        lua_pushstring(L, luaL_typename(L, 1));
    }

    return 1;
}

/*
 * num = mongo.tonumber(obj)
 */
static int bson_tonumber(lua_State *L) {
    int base = luaL_optint(L, 2, 10);
    if (base == 10) {  /* standard conversion */
        luaL_checkany(L, 1);
        if (lua_isnumber(L, 1)) {
            lua_pushnumber(L, lua_tonumber(L, 1));
            return 1;
        } else if (lua_istable(L, 1)) {
            int bsontype_found = luaL_getmetafield(L, 1, "__bsontype");

            if (bsontype_found) {
                lua_rawgeti(L, 1, 1);

                if (lua_isnumber(L, -1)) {
                    lua_pushnumber(L, lua_tonumber(L, -1));
                    return 1;
                }

                lua_pop(L, 1);
            }
        }
    } else {
        const char *s1 = luaL_checkstring(L, 1);
        char *s2;
        unsigned long n;
        luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
        n = strtoul(s1, &s2, base);
        if (s1 != s2) {  /* at least one valid digit? */
            while (isspace((unsigned char)(*s2))) s2++;  /* skip trailing spaces */
            if (*s2 == '\0') {  /* no invalid trailing characters? */
                lua_pushnumber(L, (lua_Number)n);
                return 1;
            }
        }
    }

    lua_pushnil(L);  /* else not a number */
    return 1;
}

static int bson_tojson(lua_State *L) {
    int resultcount = 1;
    BSONObj obj;

    if (lua_istable(L, 1)) {
        lua_to_bson(L, 1, obj);

        lua_pushstring(L, obj.toString().c_str());
    } else {
        lua_pushnil(L);
        lua_pushfstring(L, "Argument is not a table");
        resultcount = 2;
    }

    return resultcount;
}

static int bson_fromjson(lua_State *L) {
    const char *json = luaL_checkstring(L, 1);
    int resultcount = 1;
    BSONObj obj;

    try {
        bson_to_lua(L, fromjson(json));
    } catch (std::exception &e) {
        lua_pushnil(L);
        lua_pushfstring(L, "Error parsing JSON: %s", e.what());
        resultcount = 2;
    }

    return resultcount;
}

int mongo_bsontypes_register(lua_State *L) {
    static const luaL_Reg bsontype_methods[] = {
        {"Date", bson_type_Date},
        {"Timestamp", bson_type_Timestamp},
        {"RegEx", bson_type_RegEx},
        {"NumberInt", bson_type_NumberInt},
        {"NumberLong", bson_type_NumberLong},
        {"Symbol", bson_type_Symbol},
        {"ObjectId", bson_type_ObjectID},
        {"NULL", bson_type_NULL},

        // Utils
        {"type", bson_type_name},
        {"tonumber", bson_tonumber},
        {"tojson", bson_tojson},
        {"fromjson", bson_fromjson},
        {NULL, NULL}
    };

    luaL_register(L, LUAMONGO_ROOT, bsontype_methods);

    return 1;
}

<|endoftext|>


<commit_before>#include <iostream>
#include <cstdio>
#include <sstream>
#include <vector>
#include <cstdlib>
#include <sys/wait.h>
#include <unistd.h>
#include "pugixml/pugixml.cpp"

void showUsage(){
	std::cout << "Usage: ./readtxt [OPTIONS] [FILENAME]" << std::endl;
	//std::cout << "\tOPTIONS GO HERE" << std::endl;
	std::cout << "\t-h:\tDisplays this help message." << std::endl;
	std::cout << "\t-a ADDRESS:\tSpecifies the conversation by address" << std::endl;
	std::cout << "\t-l:\tLists all conversations by address" << std::endl;
	std::cout << "\t-s:\tSends thread data directly to stdout" << std::endl;
	exit(EXIT_FAILURE);
}

std::string getFileName(){
	std::string file_name;

	std::cout << "File> ";
	std::getline(std::cin, file_name);

	return file_name;
}

std::string threadToString(pugi::xml_node thread){
	std::stringstream ss;

	for (pugi::xml_node sms = thread.child("sms"); sms; sms = sms.next_sibling("sms")){
		std::string date = sms.attribute("dateSent").value();
		if(date.empty())
			date = sms.attribute("date").value();
		ss << "[" << date << "] " << sms.attribute("address").value() << ": ";
		ss << sms.child_value() << std::endl;

	}

	return std::string(ss.str());

}

int main(int argc, char **argv){
	bool list_addresses = false;
	bool display_less = true;
	std::string file_name;
	std::string address;
	std::string input;
	std::string thread_string;
	pugi::xml_document doc; // text message doc
	int index;
	int c;

	opterr = 0;

	while ((c = getopt(argc, argv, "ha:ls")) != -1){
		switch(c){
			case 'a':
				address = optarg;
				break;
			case 'l':
				list_addresses = true;
				break;
			case 's':
				display_less = false;
				break;
			case '?':
				if(optopt == 'c')
					std::cerr << "Option -" << optopt << "requires an argument." << std::endl;
				else if(isprint(optopt))
					std::cerr << "Unknown option `-" << optopt << "'." << std::endl;
				else
					fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt);
					return EXIT_FAILURE;
			case 'h':
			default:
				showUsage();
		}
	}

	if(argc - optind > 1)
		showUsage();

	for (index = optind; index < argc; index++){
		file_name = argv[index];
	}

	if(file_name.empty())
		file_name = getFileName();

	std::cout << "Reading from file " << file_name << std::endl;

	pugi::xml_parse_result result = doc.load_file(file_name.c_str());

	pugi::xml_node threads = doc.child("threads");

	std::cout << "Load result: " << result.description() << ", Thread count: " << threads.attribute("count").value() << std::endl;

	if(list_addresses){
		for (pugi::xml_node thread = threads.child("thread"); thread; thread = thread.next_sibling("thread")){
			std::cout << thread.attribute("address").value() << std::endl;
			//threads.push_back(thread);

		}
	}
	else{
		if(address.empty()){
			std::cout << "Address> ";
			std::getline(std::cin, input);
			address = input;
		}
		thread_string = threadToString(threads.find_child_by_attribute("thread", "address", address.c_str()));
		if(display_less){
			int pip[2];
			int result;
			pid_t pid;
			result = pipe(pip);
			if(result == -1){
				perror("pipe");
				exit(EXIT_FAILURE);
			}
			pid = fork();
			if(pid > 0){
				// parent
				int status;
				close(pip[0]);
				write(pip[1], thread_string.c_str(), thread_string.length());
				close(pip[1]);
				wait(&status);
				fprintf(stderr, "Exit status: %d\n", WEXITSTATUS(status));
			}
			else if(pid == 0){
				// child
				close(pip[1]);
				dup2(pip[0], STDIN_FILENO);
				execlp("/usr/bin/less", "less", NULL);
			}
			else{
				perror("fork");
				exit(EXIT_FAILURE);
			}
		}
		else{
			std::cout << thread_string;
		}
	}

	return EXIT_SUCCESS;
}<commit_msg>some more refactoring and interactive mode stuff<commit_after>#include <iostream>
#include <cstdio>
#include <sstream>
#include <vector>
#include <cstdlib>
#include <sys/wait.h>
#include <unistd.h>
#include "pugixml/pugixml.cpp"

void show_usage(){
	std::cout << "Usage: ./readtxt [OPTIONS] [FILENAME]" << std::endl;
	//std::cout << "\tOPTIONS GO HERE" << std::endl;
	std::cout << "\t-h:\tDisplays this help message." << std::endl;
	std::cout << "\t-a ADDR: Specifies the conversation by address" << std::endl;
	std::cout << "\t-i:\tInteractive mode." << std::endl;
	std::cout << "\t-l:\tLists all conversations by address" << std::endl;
	std::cout << "\t-s:\tSends thread data directly to stdout" << std::endl;
	exit(EXIT_FAILURE);
}

std::string get_filename(){
	std::string file_name;

	std::cout << "File> ";
	std::getline(std::cin, file_name);

	return file_name;
}

std::vector<std::string> get_addresses(pugi::xml_node threads){
	std::vector<std::string> address_list;
	for (pugi::xml_node thread = threads.child("thread"); thread; thread = thread.next_sibling("thread"))
		address_list.push_back(thread.attribute("address").value());
	return address_list;
}

std::string threadToString(pugi::xml_node thread){
	std::stringstream ss;

	for (pugi::xml_node sms = thread.child("sms"); sms; sms = sms.next_sibling("sms")){
		std::string date = sms.attribute("dateSent").value();
		if(date.empty())
			date = sms.attribute("date").value();
		ss << "[" << date << "] " << sms.attribute("address").value() << ": ";
		ss << sms.child_value() << std::endl;

	}

	return std::string(ss.str());

}

void send_to_less(std::string str){
	int pip[2];
	int result;
	pid_t pid;
	result = pipe(pip);
	if(result == -1){
		perror("pipe");
		exit(EXIT_FAILURE);
	}
	pid = fork();
	if(pid > 0){
		// parent
		int status;
		close(pip[0]);
		write(pip[1], str.c_str(), str.length());
		close(pip[1]);
		wait(&status);
		fprintf(stderr, "Exit status: %d\n", WEXITSTATUS(status));
	}
	else if(pid == 0){
		// child
		close(pip[1]);
		dup2(pip[0], STDIN_FILENO);
		execlp("/usr/bin/less", "less", NULL);
	}
	else{
		perror("fork");
		exit(EXIT_FAILURE);
	}
}

int main(int argc, char **argv){
	bool interactive = false;
	bool list_addresses = false;
	bool display_less = true;
	std::string file_name;
	std::string address;
	std::string input;
	std::string thread_string;
	pugi::xml_document doc; // text message doc
	int index;
	int c;

	opterr = 0;

	while ((c = getopt(argc, argv, "iha:ls")) != -1){
		switch(c){
			case 'a':
				address = optarg;
				break;
			case 'l':
				list_addresses = true;
				break;
			case 's':
				display_less = false;
				break;
			case 'i':
				interactive = true;
				break;
			case '?':
				if(optopt == 'c')
					std::cerr << "Option -" << optopt << "requires an argument." << std::endl;
				else if(isprint(optopt))
					std::cerr << "Unknown option `-" << optopt << "'." << std::endl;
				else
					fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt);
					return EXIT_FAILURE;
			case 'h':
			default:
				show_usage();
		}
	}

	if(argc - optind > 1)
		show_usage();

	for (index = optind; index < argc; index++){
		file_name = argv[index];
	}

	if(file_name.empty() && interactive)
		file_name = get_filename();
	else
		show_usage();

	std::cout << "Reading from file " << file_name << std::endl;

	pugi::xml_parse_result result = doc.load_file(file_name.c_str());

	pugi::xml_node threads = doc.child("threads");

	std::cout << "Load result: " << result.description() << ", Thread count: " << threads.attribute("count").value() << std::endl;

	if(list_addresses){
		std::vector<std::string> addresses = get_addresses(threads);
		for(auto address: addresses){
			std::cout << address << std::endl;
		}
	}
	else{
		if(address.empty() && interactive){
			std::cout << "Address> ";
			std::getline(std::cin, input);
			address = input;
		}
		else
			show_usage();
		thread_string = threadToString(threads.find_child_by_attribute("thread", "address", address.c_str()));
		if(display_less){
			send_to_less(thread_string);
		}
		else{
			std::cout << thread_string;
		}
	}

	return EXIT_SUCCESS;
}<|endoftext|>


<commit_before>#ifndef TYPES_HPP_
#define TYPES_HPP_

#include "complex-half.hpp"

#include <boost/mpl/list.hpp>

#include <array>
#include <vector>
#include <iostream>
#include <algorithm>
#include <complex>
#include <type_traits>

namespace gearshifft {
  using Extents1D = std::array<size_t,1>;
  using Extents2D = std::array<size_t,2>;
  using Extents3D = std::array<size_t,3>;
  using Extents1DVec = std::vector< Extents1D >;
  using Extents2DVec = std::vector< Extents2D >;
  using Extents3DVec = std::vector< Extents3D >;

/// List alias
  template<typename... Types>
  using List = boost::mpl::list<Types...>;

  namespace interpret_as {
    template<typename T_Extents>
    T_Extents column_major(T_Extents e) {
      return e;
    }
    template<typename T_Extents>
    T_Extents row_major(T_Extents e) {
      std::reverse(e.begin(), e.end());
      return e;
    }
  }

  template<typename T>
  struct ErrorBound {
    static constexpr int PrecisionDigits =
      std::conditional<std::is_same<float16, T>::value, std::integral_constant<int, 3>, std::integral_constant<int, std::numeric_limits<T>::digits10>>::type::value;

    double operator()() {
      return pow(10.0,-PrecisionDigits);
    }
  };

  template<size_t NDim>
  inline
  std::ostream& operator<<(std::ostream& os, const std::array<size_t,NDim>& e) {
    os << e[0];
    for(size_t k=1; k<NDim; ++k) {
      if(e[k]==0)
        break;
      os << "x" << e[k];
    }
    return os;
  }

  /**
   * Basic 2D vector with template type.
   * Used for test data for complex FFTs
   */
#if GEARSHIFFT_FLOAT16_SUPPORT == 0
  template<typename REAL>
  using Real2D = std::complex<REAL>;
#else
  template<typename REAL>
  using Real2D = typename std::conditional<std::is_same<REAL,float16>::value, gearshifft::complex<float16>, std::complex<REAL> >::type;
#endif

#if GEARSHIFFT_PRECISION_DOUBLE_ONLY==1
  using DefaultPrecisions                     = List<double>;
  using DefaultPrecisionsWithoutHalfPrecision = DefaultPrecisions;
#elif GEARSHIFFT_PRECISION_SINGLE_ONLY==1
  using DefaultPrecisions                     = List<float>;
  using DefaultPrecisionsWithoutHalfPrecision = DefaultPrecisions;
#else
# if GEARSHIFFT_FLOAT16_SUPPORT==1
#  if GEARSHIFFT_PRECISION_HALF_ONLY==1
  using DefaultPrecisions                     = List<float16>;
  using DefaultPrecisionsWithoutHalfPrecision = List<>;
#  else
  using DefaultPrecisions                     = List<float, double, float16>;
  using DefaultPrecisionsWithoutHalfPrecision = List<float, double>;
#  endif
# else
  using DefaultPrecisions                     = List<float, double>;
  using DefaultPrecisionsWithoutHalfPrecision = DefaultPrecisions;
# endif
#endif

  enum struct RecordType {
    Allocation = 0,
    PlanInitFwd,
    PlanInitInv,
    Upload,
    FFT,
    FFTInv,
    Download,
    PlanDestroy,
    Total,
    DevBufferSize,
    DevPlanSize,
    DevTransferSize,
    Deviation,
    Mismatches,
    _NrRecords
  };

  inline
  std::ostream& operator<< (std::ostream & os, RecordType r) {
    switch (r) {
    case RecordType::Allocation: return os << "Time_Allocation [ms]";
    case RecordType::PlanInitFwd: return os << "Time_PlanInitFwd [ms]";
    case RecordType::PlanInitInv: return os << "Time_PlanInitInv [ms]";
    case RecordType::Upload: return os << "Time_Upload [ms]";
    case RecordType::FFT: return os << "Time_FFT [ms]";
    case RecordType::FFTInv: return os << "Time_iFFT [ms]";
    case RecordType::Download: return os << "Time_Download [ms]";
    case RecordType::PlanDestroy: return os << "Time_PlanDestroy [ms]";
    case RecordType::Total: return os << "Time_Total [ms]";
    case RecordType::DevBufferSize: return os << "Size_DeviceBuffer [bytes]";
    case RecordType::DevPlanSize: return os << "Size_DevicePlan [bytes]";
    case RecordType::DevTransferSize: return os << "Size_DeviceTransfer [bytes]";
    case RecordType::Deviation: return os << "Error_StandardDeviation";
    case RecordType::Mismatches: return os << "Error_Mismatches";
    case RecordType::_NrRecords:
    default:
      ;
    }
    return os << static_cast<int>(r);
  }
}
#endif
<commit_msg>Defines BOOST_SYSTEM_NO_DEPRECATED.<commit_after>#ifndef TYPES_HPP_
#define TYPES_HPP_

// https://github.com/mpicbg-scicomp/gearshifft/issues/145
#include <boost/predef.h>
#if BOOST_VERSION < 106600
#define BOOST_SYSTEM_NO_DEPRECATED
#endif

#include "complex-half.hpp"

#include <boost/mpl/list.hpp>

#include <array>
#include <vector>
#include <iostream>
#include <algorithm>
#include <complex>
#include <type_traits>

namespace gearshifft {
  using Extents1D = std::array<size_t,1>;
  using Extents2D = std::array<size_t,2>;
  using Extents3D = std::array<size_t,3>;
  using Extents1DVec = std::vector< Extents1D >;
  using Extents2DVec = std::vector< Extents2D >;
  using Extents3DVec = std::vector< Extents3D >;

/// List alias
  template<typename... Types>
  using List = boost::mpl::list<Types...>;

  namespace interpret_as {
    template<typename T_Extents>
    T_Extents column_major(T_Extents e) {
      return e;
    }
    template<typename T_Extents>
    T_Extents row_major(T_Extents e) {
      std::reverse(e.begin(), e.end());
      return e;
    }
  }

  template<typename T>
  struct ErrorBound {
    static constexpr int PrecisionDigits =
      std::conditional<std::is_same<float16, T>::value, std::integral_constant<int, 3>, std::integral_constant<int, std::numeric_limits<T>::digits10>>::type::value;

    double operator()() {
      return pow(10.0,-PrecisionDigits);
    }
  };

  template<size_t NDim>
  inline
  std::ostream& operator<<(std::ostream& os, const std::array<size_t,NDim>& e) {
    os << e[0];
    for(size_t k=1; k<NDim; ++k) {
      if(e[k]==0)
        break;
      os << "x" << e[k];
    }
    return os;
  }

  /**
   * Basic 2D vector with template type.
   * Used for test data for complex FFTs
   */
#if GEARSHIFFT_FLOAT16_SUPPORT == 0
  template<typename REAL>
  using Real2D = std::complex<REAL>;
#else
  template<typename REAL>
  using Real2D = typename std::conditional<std::is_same<REAL,float16>::value, gearshifft::complex<float16>, std::complex<REAL> >::type;
#endif

#if GEARSHIFFT_PRECISION_DOUBLE_ONLY==1
  using DefaultPrecisions                     = List<double>;
  using DefaultPrecisionsWithoutHalfPrecision = DefaultPrecisions;
#elif GEARSHIFFT_PRECISION_SINGLE_ONLY==1
  using DefaultPrecisions                     = List<float>;
  using DefaultPrecisionsWithoutHalfPrecision = DefaultPrecisions;
#else
# if GEARSHIFFT_FLOAT16_SUPPORT==1
#  if GEARSHIFFT_PRECISION_HALF_ONLY==1
  using DefaultPrecisions                     = List<float16>;
  using DefaultPrecisionsWithoutHalfPrecision = List<>;
#  else
  using DefaultPrecisions                     = List<float, double, float16>;
  using DefaultPrecisionsWithoutHalfPrecision = List<float, double>;
#  endif
# else
  using DefaultPrecisions                     = List<float, double>;
  using DefaultPrecisionsWithoutHalfPrecision = DefaultPrecisions;
# endif
#endif

  enum struct RecordType {
    Allocation = 0,
    PlanInitFwd,
    PlanInitInv,
    Upload,
    FFT,
    FFTInv,
    Download,
    PlanDestroy,
    Total,
    DevBufferSize,
    DevPlanSize,
    DevTransferSize,
    Deviation,
    Mismatches,
    _NrRecords
  };

  inline
  std::ostream& operator<< (std::ostream & os, RecordType r) {
    switch (r) {
    case RecordType::Allocation: return os << "Time_Allocation [ms]";
    case RecordType::PlanInitFwd: return os << "Time_PlanInitFwd [ms]";
    case RecordType::PlanInitInv: return os << "Time_PlanInitInv [ms]";
    case RecordType::Upload: return os << "Time_Upload [ms]";
    case RecordType::FFT: return os << "Time_FFT [ms]";
    case RecordType::FFTInv: return os << "Time_iFFT [ms]";
    case RecordType::Download: return os << "Time_Download [ms]";
    case RecordType::PlanDestroy: return os << "Time_PlanDestroy [ms]";
    case RecordType::Total: return os << "Time_Total [ms]";
    case RecordType::DevBufferSize: return os << "Size_DeviceBuffer [bytes]";
    case RecordType::DevPlanSize: return os << "Size_DevicePlan [bytes]";
    case RecordType::DevTransferSize: return os << "Size_DeviceTransfer [bytes]";
    case RecordType::Deviation: return os << "Error_StandardDeviation";
    case RecordType::Mismatches: return os << "Error_Mismatches";
    case RecordType::_NrRecords:
    default:
      ;
    }
    return os << static_cast<int>(r);
  }
}
#endif
<|endoftext|>


<commit_before>#ifndef Matrix_hpp
#define Matrix_hpp

#include <iostream>
#include <fstream>

class Matrix {
public:
	Matrix() : lines(0), columns(0), elements(nullptr) {}
	Matrix(int _lines, int _columns);
	Matrix(const Matrix& source_matrix);
	Matrix& operator= (const Matrix& source_matrix);
	void InitFromRandom();
	void InitFromFile(const char *filename);
	void Output() const;
	int* operator[](int index) const;
	Matrix operator+(const Matrix& right_matrix) const;
	Matrix operator*(const Matrix& right_matrix) const;
	int GetNumberOfLines() const;
	int GetNumberOfColumns() const;
	~Matrix();
private:
	int lines, columns, **elements;
};

Matrix::Matrix(int _lines, int _columns)  :
	lines(_lines), columns(_columns), elements(new int*[_lines]) {
	for (int i = 0; i < lines; i++) {
		elements[i] = new int[columns];
		for (int j = 0; j < columns; j++){
			elements[i][j] = 0;
		}
	}
}
Matrix::Matrix(const Matrix& source_matrix)
	: lines(source_matrix.lines), columns(source_matrix.columns) {
	elements = new int*[lines];
	for (int i = 0; i < lines; i++) {
		elements[i] = new int[columns];
		for (int j  = 0; j < columns; j++) {
			elements[i][j] = source_matrix[i][j];
		}
	}
}
Matrix& Matrix::operator= (const Matrix& source_matrix) {
	if (lines != source_matrix.lines || columns != source_matrix.columns) {
		this -> ~Matrix();
		lines = source_matrix.lines;
		columns = source_matrix.columns;
		elements = new int*[lines];
		for (int i = 0; i < lines; i++) {
			elements[i] = new int[columns];
			for (int j = 0; j < columns; j++) {
				elements[i][j] = source_matrix[i][j];
			}
		}
	} else{
		for (int i = 0; i < lines; i++){
			for (int j = 0; j < columns; j++){
				elements[i][j] = source_matrix[i][j];
			}
		}
	}
	return *this;
}
void Matrix::InitFromRandom() {
	for (int i = 0; i < lines; i++)
		for (int j = 0; j < columns; j++)
			elements[i][j] = rand() % 90 + 10;
}
void Matrix::InitFromFile(const char *filename) {
	std::fstream file(filename);
	for (int i = 0; i < lines; i++) {
		for (int j = 0; j < columns; j++) {
			file >> elements[i][j];
		}
	}
}
void Matrix::Output() const {
	for (int i = 0; i < lines; i++) {
		for (int j = 0; j < columns; j++)
			std::cout << elements[i][j] << " ";
		std::cout << "\n";
	}
}
int*  Matrix::operator[](int index) const {
	return elements[index];
}
Matrix Matrix::operator+(const Matrix& right_matrix) const {
	if (columns != right_matrix.GetNumberOfColumns()
		|| lines != right_matrix.GetNumberOfLines())
		return *(new Matrix());
	Matrix result(lines, columns);
	for (int i = 0; i < lines; i++)
		for (int j = 0; j < columns; j++)
			result[i][j] = elements[i][j] + right_matrix[i][j];
	return result;
}
Matrix Matrix::operator*(const Matrix& right_matrix) const {
	if (columns != right_matrix.lines) return *(new Matrix());
	Matrix result(lines, right_matrix.columns);
	for (int i = 0; i < lines; i++)
		for (int j = 0; j < right_matrix.columns; j++) {
			result[i][j] = 0;
			for (int k = 0; k < right_matrix.lines; k++)
				result[i][j] += elements[i][k] * right_matrix[k][j];
		}
	return result;
}
int Matrix::GetNumberOfLines() const {
	return lines;
}
int Matrix::GetNumberOfColumns() const {
	return columns;
}
Matrix::~Matrix() {
	for (int i = 0; i < lines; i++)
		delete[] elements[i];
	delete[] elements;
}

#endif
<commit_msg>Update Matrix.hpp<commit_after>#ifndef Matrix_hpp
#define Matrix_hpp

#include <iostream>
#include <fstream>
/*template <typename MatrixT>
class Matrix;

template <typename MatrixT>
std::ostream& operator<<(std::ostream&, const Matrix<MatrixT> &);*/

template <typename MatrixT>
class Matrix {
public:
	Matrix() : lines(0), columns(0), elements(nullptr) {}
	Matrix(unsigned int _lines, unsigned int _columns);
	Matrix(const Matrix<MatrixT>& source_matrix);
	Matrix& operator= (const Matrix& source_matrix);
	void InitFromRandom();
	void InitFromFile(const char *filename);
	template <typename MatrixT>
	friend std::istream& operator>> (std::istream& stream, Matrix<MatrixT>& matrix);
	template <typename MatrixT>
	friend std::ostream& operator<< (std::ostream& stream, const Matrix<MatrixT>& matrix);
	MatrixT* operator[](unsigned int index) const;
	Matrix<MatrixT> operator+(const Matrix<MatrixT>& right_matrix) const;
	Matrix<MatrixT> operator*(const Matrix<MatrixT>& right_matrix) const;
	unsigned int GetNumberOfLines() const;
	unsigned int GetNumberOfColumns() const;
	~Matrix();
private:
	MatrixT **elements;
	unsigned int lines, columns;
};

template <typename MatrixT>
Matrix<MatrixT>::Matrix(unsigned int _lines, unsigned int _columns)  :
	lines(_lines), columns(_columns), elements(new MatrixT*[_lines]) {
	for (unsigned int i = 0; i < lines; i++) {
		elements[i] = new MatrixT[columns];
		for (unsigned int j = 0; j < columns; j++){
			elements[i][j] = 0;
		}
	}
}

template <typename MatrixT>
Matrix<MatrixT>::Matrix(const Matrix<MatrixT>& source_matrix)
	: lines(source_matrix.lines), columns(source_matrix.columns) {
	elements = new MatrixT*[lines];
	for (unsigned int i = 0; i < lines; i++) {
		elements[i] = new MatrixT[columns];
		for (unsigned int j  = 0; j < columns; j++) {
			elements[i][j] = source_matrix[i][j];
		}
	}
}

template <typename MatrixT>
Matrix<MatrixT>& Matrix<MatrixT>::operator= (const Matrix<MatrixT>& source_matrix) {
	if (lines != source_matrix.lines || columns != source_matrix.columns) {
		this -> ~Matrix();
		lines = source_matrix.lines;
		columns = source_matrix.columns;
		elements = new int*[lines];
		for (int i = 0; i < lines; i++) {
			elements[i] = new int[columns];
			for (int j = 0; j < columns; j++) {
				elements[i][j] = source_matrix[i][j];
			}
		}
	} else{
		for (int i = 0; i < lines; i++){
			for (int j = 0; j < columns; j++){
				elements[i][j] = source_matrix[i][j];
			}
		}
	}
	return *this;
}

template <typename MatrixT>
std::istream& operator>> (std::istream& stream, Matrix<MatrixT>& matrix){
	for (unsigned int i = 0; i < matrix.lines; i++){
		for (unsigned int j = 0; j < matrix.columns; j++){
			stream >> matrix[i][j];
		}
	}
	return stream;
}

template <typename MatrixT>
std::ostream& operator<< (std::ostream& stream, const Matrix<MatrixT>& matrix){
	for (unsigned int i = 0; i < matrix.lines; i++){
		for (unsigned int j = 0; j < matrix.columns; j++){
			stream << matrix[i][j] << " ";
		}
		stream << '\n';
	}
	return stream;
}

template <typename MatrixT>
void Matrix<MatrixT>::InitFromRandom() {
	for (int i = 0; i < lines; i++){
		for (int j = 0; j < columns; j++){
			elements[i][j] = rand() % 90 + 10;
		}
	}
}

template <typename MatrixT>
void Matrix<MatrixT>::InitFromFile(const char *filename) {
	std::fstream file(filename);
	if (!file) throw "File cannot be opened";
	file >> *this;
	/*for (int i = 0; i < lines; i++) {
		for (int j = 0; j < columns; j++) {
			file >> elements[i][j];
		}
	}*/
}

template <typename MatrixT>
MatrixT* Matrix<MatrixT>::operator[](unsigned int index) const {
	if (index >= lines) throw "index >= lines";
	return elements[index];
}

template <typename MatrixT>
Matrix<MatrixT> Matrix<MatrixT>::operator+(const Matrix<MatrixT>& right_matrix) const {
	if (columns != right_matrix.GetNumberOfColumns()
		|| lines != right_matrix.GetNumberOfLines())
		throw "left_matrix.columns != right_matrix.columns || left_matrix.lines != right_matix.lines";
	Matrix<MatrixT> result(lines, columns);
	for (int i = 0; i < lines; i++){
		for (int j = 0; j < columns; j++){
			result[i][j] = elements[i][j] + right_matrix[i][j];
		}
	}
	return result;
}

template <typename MatrixT>
Matrix<MatrixT> Matrix<MatrixT>::operator*(const Matrix& right_matrix) const {
	if (columns != right_matrix.lines) throw "left_matrix.columns != right_matrix.lines";
	Matrix<MatrixT> result(lines, right_matrix.columns);
	for (int i = 0; i < lines; i++)
		for (int j = 0; j < right_matrix.columns; j++) {
			result[i][j] = 0;
			for (int k = 0; k < right_matrix.lines; k++)
				result[i][j] += elements[i][k] * right_matrix[k][j];
		}
	return result;
}

template <typename MatrixT>
unsigned int Matrix<MatrixT>::GetNumberOfLines() const {
	return lines;
}

template <typename MatrixT>
unsigned int Matrix<MatrixT>::GetNumberOfColumns() const {
	return columns;
}

template <typename MatrixT>
Matrix<MatrixT>::~Matrix() {
	for (unsigned int i = 0; i < lines; i++)
		delete[] elements[i];
	delete[] elements;
}

#endif
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2013-2018 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include <vector>
#include <string>
#include <map>

#include "module_traits.hpp"
#include "money.hpp"
#include "date.hpp"
#include "writer_fwd.hpp"
#include "filter_iterator.hpp"

namespace budget {

struct assets_module {
    void load();
    void unload();
    void handle(const std::vector<std::string>& args);
};

template<>
struct module_traits<assets_module> {
    static constexpr const bool is_default = false;
    static constexpr const char* command = "asset";
};

struct asset {
    size_t id;
    std::string guid;
    std::string name;
    money int_stocks;
    money dom_stocks;
    money bonds;
    money cash;
    std::string currency;
    bool portfolio;
    money portfolio_alloc;
    bool share_based;
    std::string ticker;

    std::map<std::string, std::string> get_params();

    money total_allocation() const {
        return int_stocks + dom_stocks + bonds + cash;
    }

    bool is_cash() const {
        return cash == budget::money(100);
    }
};

// Used to set the value of the asset
struct asset_value {
    size_t id;
    std::string guid;
    size_t asset_id;
    budget::money amount;
    budget::date set_date;

    std::map<std::string, std::string> get_params();
};

// Used to indicate purchase of shares
struct asset_share {
    size_t id;
    std::string guid;
    size_t asset_id;
    size_t shares;       // The number of shares
    budget::money price; // The purchase price
    budget::date date;   // The purchase date

    std::map<std::string, std::string> get_params();
};

std::ostream& operator<<(std::ostream& stream, const asset& asset);
void operator>>(const std::vector<std::string>& parts, asset& asset);

std::ostream& operator<<(std::ostream& stream, const asset_value& asset);
void operator>>(const std::vector<std::string>& parts, asset_value& asset);

std::ostream& operator<<(std::ostream& stream, const asset_share& asset);
void operator>>(const std::vector<std::string>& parts, asset_share& asset);

void load_assets();
void save_assets();

void migrate_assets_4_to_5();

void show_assets(budget::writer& w);
void list_asset_values(budget::writer& w);
void small_show_asset_values(budget::writer& w);
void show_asset_values(budget::writer& w);
void show_asset_portfolio(budget::writer& w);
void show_asset_rebalance(budget::writer& w, bool nocash = false);

void list_asset_shares(budget::writer& w);

bool asset_exists(const std::string& asset);
bool share_asset_exists(const std::string& asset);

budget::asset& get_asset(size_t id);
budget::asset& get_asset(std::string name);

budget::asset_value& get_asset_value(size_t id);
budget::asset_share& get_asset_share(size_t id);

budget::asset& get_desired_allocation();

std::vector<budget::asset>& all_assets();
std::vector<budget::asset_value>& all_asset_values();
std::vector<budget::asset_share>& all_asset_shares();

budget::date asset_start_date();
budget::date asset_start_date(const asset& asset);

void set_assets_next_id(size_t next_id);
void set_asset_values_next_id(size_t next_id);
void set_asset_shares_next_id(size_t next_id);

void set_assets_changed();
void set_asset_values_changed();
void set_asset_shares_changed();

std::string get_default_currency();

void add_asset(asset&& asset);
bool asset_exists(size_t id);
void asset_delete(size_t id);
asset& asset_get(size_t id);

void add_asset_value(asset_value&& asset_value);
bool asset_value_exists(size_t id);
void asset_value_delete(size_t id);
asset_value& asset_value_get(size_t id);

void add_asset_share(asset_share&& asset_share);
bool asset_share_exists(size_t id);
void asset_share_delete(size_t id);
asset_share& asset_share_get(size_t id);

budget::money get_portfolio_value();
budget::money get_net_worth();
budget::money get_net_worth_cash();

budget::money get_net_worth(budget::date d);

// The value of an assert in its own currency
budget::money get_asset_value(budget::asset & asset);
budget::money get_asset_value(budget::asset & asset, budget::date d);

// The value of an assert in the default currency
budget::money get_asset_value_conv(budget::asset & asset);
budget::money get_asset_value_conv(budget::asset & asset, budget::date d);

// The value of an assert in a specific currency
budget::money get_asset_value_conv(budget::asset & asset, const std::string& currency);
budget::money get_asset_value_conv(budget::asset & asset, budget::date d, const std::string& currency);

// Filter functions

inline auto all_user_assets() {
    return make_filter_view(begin(all_assets()), end(all_assets()), [=](const asset& a) {
        return a.name != "DESIRED";
    });
}

} //end of namespace budget
<commit_msg>Allow negative shares<commit_after>//=======================================================================
// Copyright (c) 2013-2018 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include <vector>
#include <string>
#include <map>

#include "module_traits.hpp"
#include "money.hpp"
#include "date.hpp"
#include "writer_fwd.hpp"
#include "filter_iterator.hpp"

namespace budget {

struct assets_module {
    void load();
    void unload();
    void handle(const std::vector<std::string>& args);
};

template<>
struct module_traits<assets_module> {
    static constexpr const bool is_default = false;
    static constexpr const char* command = "asset";
};

struct asset {
    size_t id;
    std::string guid;
    std::string name;
    money int_stocks;
    money dom_stocks;
    money bonds;
    money cash;
    std::string currency;
    bool portfolio;
    money portfolio_alloc;
    bool share_based;
    std::string ticker;

    std::map<std::string, std::string> get_params();

    money total_allocation() const {
        return int_stocks + dom_stocks + bonds + cash;
    }

    bool is_cash() const {
        return cash == budget::money(100);
    }
};

// Used to set the value of the asset
struct asset_value {
    size_t id;
    std::string guid;
    size_t asset_id;
    budget::money amount;
    budget::date set_date;

    std::map<std::string, std::string> get_params();
};

// Used to indicate purchase of shares
struct asset_share {
    size_t id;
    std::string guid;
    size_t asset_id;
    int64_t shares;      // The number of shares
    budget::money price; // The purchase price
    budget::date date;   // The purchase date

    std::map<std::string, std::string> get_params();

    bool is_buy() const {
        return shares >= 0;
    }

    bool is_sell() const {
        return shares < 0;
    }
};

std::ostream& operator<<(std::ostream& stream, const asset& asset);
void operator>>(const std::vector<std::string>& parts, asset& asset);

std::ostream& operator<<(std::ostream& stream, const asset_value& asset);
void operator>>(const std::vector<std::string>& parts, asset_value& asset);

std::ostream& operator<<(std::ostream& stream, const asset_share& asset);
void operator>>(const std::vector<std::string>& parts, asset_share& asset);

void load_assets();
void save_assets();

void migrate_assets_4_to_5();

void show_assets(budget::writer& w);
void list_asset_values(budget::writer& w);
void small_show_asset_values(budget::writer& w);
void show_asset_values(budget::writer& w);
void show_asset_portfolio(budget::writer& w);
void show_asset_rebalance(budget::writer& w, bool nocash = false);

void list_asset_shares(budget::writer& w);

bool asset_exists(const std::string& asset);
bool share_asset_exists(const std::string& asset);

budget::asset& get_asset(size_t id);
budget::asset& get_asset(std::string name);

budget::asset_value& get_asset_value(size_t id);
budget::asset_share& get_asset_share(size_t id);

budget::asset& get_desired_allocation();

std::vector<budget::asset>& all_assets();
std::vector<budget::asset_value>& all_asset_values();
std::vector<budget::asset_share>& all_asset_shares();

budget::date asset_start_date();
budget::date asset_start_date(const asset& asset);

void set_assets_next_id(size_t next_id);
void set_asset_values_next_id(size_t next_id);
void set_asset_shares_next_id(size_t next_id);

void set_assets_changed();
void set_asset_values_changed();
void set_asset_shares_changed();

std::string get_default_currency();

void add_asset(asset&& asset);
bool asset_exists(size_t id);
void asset_delete(size_t id);
asset& asset_get(size_t id);

void add_asset_value(asset_value&& asset_value);
bool asset_value_exists(size_t id);
void asset_value_delete(size_t id);
asset_value& asset_value_get(size_t id);

void add_asset_share(asset_share&& asset_share);
bool asset_share_exists(size_t id);
void asset_share_delete(size_t id);
asset_share& asset_share_get(size_t id);

budget::money get_portfolio_value();
budget::money get_net_worth();
budget::money get_net_worth_cash();

budget::money get_net_worth(budget::date d);

// The value of an assert in its own currency
budget::money get_asset_value(budget::asset & asset);
budget::money get_asset_value(budget::asset & asset, budget::date d);

// The value of an assert in the default currency
budget::money get_asset_value_conv(budget::asset & asset);
budget::money get_asset_value_conv(budget::asset & asset, budget::date d);

// The value of an assert in a specific currency
budget::money get_asset_value_conv(budget::asset & asset, const std::string& currency);
budget::money get_asset_value_conv(budget::asset & asset, budget::date d, const std::string& currency);

// Filter functions

inline auto all_user_assets() {
    return make_filter_view(begin(all_assets()), end(all_assets()), [=](const asset& a) {
        return a.name != "DESIRED";
    });
}

} //end of namespace budget
<|endoftext|>


<commit_before>#pragma once

#include "pstream.hh"

class console_stream : public print_stream
{
public:
  constexpr console_stream(bool enabled = true)
    : enabled(enabled) { }

protected:
  bool enabled;

  bool begin_print()
  {
    if (!enabled)
      return false;
    _begin_print();
    return true;
  }
  void end_print();

  void write(char c);
  void write(sbuf buf);

private:
  void _begin_print();
};

class panic_stream : public console_stream
{
public:
  constexpr panic_stream() : console_stream(true) { }
protected:
  bool begin_print();
  void end_print();
};

extern console_stream console;

// Warning stream
extern console_stream swarn;

// Panic stream.  Printing to this will cause a panic.
extern panic_stream spanic;

// Errors caused by user processes (page faults, failed system calls,
// etc.)
extern console_stream uerr;
<commit_msg>kstream: Printer for windowed buffers<commit_after>#pragma once

#include "pstream.hh"

#include <string.h>

class console_stream : public print_stream
{
public:
  constexpr console_stream(bool enabled = true)
    : enabled(enabled) { }

protected:
  bool enabled;

  bool begin_print()
  {
    if (!enabled)
      return false;
    _begin_print();
    return true;
  }
  void end_print();

  void write(char c);
  void write(sbuf buf);

private:
  void _begin_print();
};

class panic_stream : public console_stream
{
public:
  constexpr panic_stream() : console_stream(true) { }
protected:
  bool begin_print();
  void end_print();
};

// A stream that captures a window of its output in a buffer.  This is
// intended for writing simple device read functions where the O(n^2)
// behavior of printing the entire output each time isn't a problem.
class window_stream : public print_stream
{
  char *out_;
  // The start and limit of the window to write to out_.
  size_t start_, lim_;
  // The number of bytes of output consumed, up to lim_.
  size_t cur_;

public:
  window_stream(char *out, size_t pos, size_t n)
    : out_(out), start_(pos), lim_(pos + n), cur_(0) { }

  // Return the number of bytes used in the output buffer.
  size_t get_used() const
  {
    if (cur_ <= start_)
      return 0;
    return cur_ - start_;
  }

protected:
  void write(sbuf buf)
  {
    if (cur_ < start_) {
      size_t skip = start_ - cur_;
      if (buf.len < skip) {
        cur_ += buf.len;
        return;
      }
      buf.base += skip;
      buf.len -= skip;
      cur_ += skip;
    }
    size_t copy = buf.len;
    if (copy > lim_ - cur_)
      copy = lim_ - cur_;
    if (copy != 0) {
      memmove(out_ + (cur_ - start_), buf.base, copy);
      cur_ += copy;
    }
    // XXX It would be nice if this could indicate to the caller when
    // to stop printing.
  }
};

extern console_stream console;

// Warning stream
extern console_stream swarn;

// Panic stream.  Printing to this will cause a panic.
extern panic_stream spanic;

// Errors caused by user processes (page faults, failed system calls,
// etc.)
extern console_stream uerr;
<|endoftext|>


<commit_before>#pragma once

template<class T>
class markptr_ptr;

template<class T>
class markptr_mark;

template<class T>
class markptr {
 protected:
  std::atomic<uptr> _p;

 public:
  markptr() : _p(0) {}
  markptr(T* v) : _p((uptr) v) {}
  markptr(const markptr<T> &v) : _p(v._p.load()) {}

  void operator=(T* v) { _p = (uptr) v; }
  void operator=(const markptr<T> &v) { _p = v._p.load(); }

  bool operator!=(const markptr<T> &v) const { return _p != v._p; }
  bool operator==(const markptr<T> &v) const { return _p == v._p; }

  markptr_ptr<T>& ptr() {
    return *(markptr_ptr<T>*) this;
  }

  markptr_mark<T>& mark() {
    return *(markptr_mark<T>*) this;
  }

  // Convenience operator to avoid having to write out xx.ptr()->...
  T* operator->() { return ptr(); }

  bool cmpxch(markptr<T> expected, markptr<T> desired) {
    uptr ee = expected._p.load();
    return _p.compare_exchange_weak(ee, desired._p.load());
  }
};

template<class T>
class markptr_ptr : private markptr<T> {
 public:
  void operator=(T* p) {
    uptr p0, p1;
    do {
      p0 = markptr<T>::_p.load();
      p1 = (p0 & 1) | (uptr) p;
    } while (!markptr<T>::_p.compare_exchange_weak(p0, p1));
  }

  bool cmpxch_update(T** expected, T* desired) {
    uptr p0, p1;
    do {
      p0 = markptr<T>::_p.load();
      p1 = (p0 & 1) | (uptr) desired;

      T* cur = (T*) (p0 & ~1);
      if (cur != *expected) {
        *expected = cur;
        return false;
      }
    } while (!markptr<T>::_p.compare_exchange_weak(p0, p1));

    return true;
  }

  T* load() const {
    return (T*) (markptr<T>::_p.load() & ~1);
  }

  operator T*() const { return load(); }
};

template<class T>
class markptr_mark : public markptr<T> {
 public:
  void operator=(bool m) {
    xchg(m);
  }

  bool xchg(bool m) {
    uptr p0, p1;
    do {
      p0 = markptr<T>::_p.load();
      p1 = (p0 & ~1) | !!m;
    } while (!markptr<T>::_p.compare_exchange_weak(p0, p1));
    return p0 & 1;
  }

  bool load() const {
    return markptr<T>::_p.load() & 1;
  }

  operator bool() const { return load(); }
};
<commit_msg>Add const versions of markptr<T>::ptr and mark<commit_after>#pragma once

template<class T>
class markptr_ptr;

template<class T>
class markptr_mark;

template<class T>
class markptr {
 protected:
  std::atomic<uptr> _p;

 public:
  markptr() : _p(0) {}
  markptr(T* v) : _p((uptr) v) {}
  markptr(const markptr<T> &v) : _p(v._p.load()) {}

  void operator=(T* v) { _p = (uptr) v; }
  void operator=(const markptr<T> &v) { _p = v._p.load(); }

  bool operator!=(const markptr<T> &v) const { return _p != v._p; }
  bool operator==(const markptr<T> &v) const { return _p == v._p; }

  markptr_ptr<T>& ptr() {
    return *(markptr_ptr<T>*) this;
  }
  const markptr_ptr<T>& ptr() const {
    return *(const markptr_ptr<T>*) this;
  }

  markptr_mark<T>& mark() {
    return *(markptr_mark<T>*) this;
  }
  const markptr_mark<T>& mark() const {
    return *(const markptr_mark<T>*) this;
  }

  // Convenience operator to avoid having to write out xx.ptr()->...
  T* operator->() { return ptr(); }

  bool cmpxch(markptr<T> expected, markptr<T> desired) {
    uptr ee = expected._p.load();
    return _p.compare_exchange_weak(ee, desired._p.load());
  }
};

template<class T>
class markptr_ptr : private markptr<T> {
 public:
  void operator=(T* p) {
    uptr p0, p1;
    do {
      p0 = markptr<T>::_p.load();
      p1 = (p0 & 1) | (uptr) p;
    } while (!markptr<T>::_p.compare_exchange_weak(p0, p1));
  }

  bool cmpxch_update(T** expected, T* desired) {
    uptr p0, p1;
    do {
      p0 = markptr<T>::_p.load();
      p1 = (p0 & 1) | (uptr) desired;

      T* cur = (T*) (p0 & ~1);
      if (cur != *expected) {
        *expected = cur;
        return false;
      }
    } while (!markptr<T>::_p.compare_exchange_weak(p0, p1));

    return true;
  }

  T* load() const {
    return (T*) (markptr<T>::_p.load() & ~1);
  }

  operator T*() const { return load(); }
};

template<class T>
class markptr_mark : public markptr<T> {
 public:
  void operator=(bool m) {
    xchg(m);
  }

  bool xchg(bool m) {
    uptr p0, p1;
    do {
      p0 = markptr<T>::_p.load();
      p1 = (p0 & ~1) | !!m;
    } while (!markptr<T>::_p.compare_exchange_weak(p0, p1));
    return p0 & 1;
  }

  bool load() const {
    return markptr<T>::_p.load() & 1;
  }

  operator bool() const { return load(); }
};
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip>
#include <fstream>

using namespace std;

class Matrix
{
private:
	int **matr;
	int st, cl;

public:
	Matrix();
	Matrix(int, int);
	Matrix(Matrix &matrc);
	~Matrix();
	int rows();
	int columns();
	Matrix operator+ (const Matrix &mat_2) const;
	Matrix operator* (const Matrix &mat_2) const;
	Matrix& operator =(Matrix &);
	bool operator==(const Matrix&)const;
	friend istream& operator >> (istream& ist, const Matrix& cmatr);
	friend ostream& operator << (ostream&, const Matrix&);
};
<commit_msg>Update matrix.hpp<commit_after>#include <iostream>
#include <iomanip>
#include <fstream>

using namespace std;

class Matrix
{
private:
	int **matr;
	int st, cl;

public:
	Matrix();
	Matrix(int, int);
	Matrix(Matrix const &matrc);
	~Matrix();
	int rows()const;
	int columns()const;
	Matrix operator+ (const Matrix &mat_2) const;
	Matrix operator* (const Matrix &mat_2) const;
	Matrix& operator =(Matrix &);
	bool operator==(const Matrix&)const;
	friend istream& operator >> (istream& ist, Matrix& cmatr);
	friend ostream& operator << (ostream&, const Matrix&);
};
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <fstream>
#include <cstdint>

using namespace std;

template <typename T>
struct Node
{
	Node *left;
	Node *right;
	T data;
};

template <typename T>
class BinaryTree;

template <typename T>
std::ostream& operator<<(std::ostream&, const BinaryTree<T>&);

template <typename T>
class BinaryTree
{
private:
	Node<T>*root;
	int count = 0;
public:
	BinaryTree();
	~BinaryTree();
	Node<T>* root_();
	unsigned int getCount()const;
	Node<T> *findNode(const T&, Node<T>*)const;
	void insertNode(const T&x);
	void deleteNode(Node<T>* temp);
	bool removeElement(Node<T>* parent, Node<T>* current, const T& val);
	bool deleteValue(const T& value);
	void write(const std::string& filename)const;
	friend std::ostream& operator<<<>(std::ostream&, const BinaryTree<T>&);
};

template <typename T>
BinaryTree<T>::BinaryTree()
{
	root = nullptr;
}

template<typename T>
Node<T>* BinaryTree<T>::root_()
{
	return root;
}

template <typename T>
BinaryTree<T>::~BinaryTree()
{
	deleteNode(root);
}

template <typename T>
unsigned int BinaryTree<T>::getCount()const
{
	return count;
}

template<typename T>
Node<T>* BinaryTree<T>::findNode(const T& data, Node<T>* temp) const
{
	if (temp == 0 || data == temp->data)
		return temp;
	if (data > temp->data)
		return findNode(data, temp->right);
	else
		return findNode(data, temp->left);
}

template<typename T>
void BinaryTree<T>::insertNode(const T&x)
{
	if (findNode(x, root_())) return;
	Node<T>* Tree = new Node<T>;
	Tree->data = x;
	Tree->left = Tree->right = 0;
	Node<T>* buff = root;
	Node<T>* temp = root;
	while (temp)
	{
		buff = temp;
		if (x < temp->data)
			temp = temp->left;
		else
			temp = temp->right;
	}
	if (!buff)
		root = Tree;
	else
	{
		if (x < buff->data)
			buff->left = Tree;
		else
			buff->right = Tree;
	}
	++count;
}

template<typename T>
void BinaryTree<T>::write(const std::string& filename)const
{
	ofstream file_1(filename);
	file_1 << count << "\t";
	output(file_1, root);
	file_1.close();
}

template<typename T>
void BinaryTree<T>::deleteNode(Node<T>* temp)
{
	if (!temp)
		return;
	if (temp->left)
	{
		deleteNode(temp->left);
		temp->left = nullptr;
	}

	if (temp->right)
	{
		deleteNode(temp->right);
		temp->right = nullptr;
	}
	delete temp;
}

template <typename T>
std::ostream& output(std::ostream& out, const Node<T>* node, unsigned int level)
{
	if (!node)
		return out;
	output(out, node->right, level + 1);
	for (unsigned int i = 0; i < level; i++)
		out << "\t";
	out << node->data << std::endl;
	output(out, node->left, level + 1);
	return out;
}

template<typename T>
bool BinaryTree<T>::removeElement(Node<T>* parent, Node<T>* current, const T& val)
{
	if (!current) return false;
	if (current->data == val)
	{
		if (current->left == NULL || current->right == NULL) {
			Node<T>* temp = current->left;
			if (current->right) temp = current->right;
			if (parent) {
				if (parent->left == current) {
					parent->left = temp;
				}
				else {
					parent->right = temp;
				}
			}
			else {
				this->root = temp;
			}
		}
		/*else {
			Node<T>* validSubs = current->right;
			while (validSubs->left) {
				validSubs = validSubs->left;
			}
			T temp = current->data;
			current->data = validSubs->data;
			validSubs->data = temp;
			return removeElement(current, current->right, temp);
		}*/
		else {
			Node<T>* validSubs = current->left;
			while (validSubs->right) {
				validSubs = validSubs->right;
			}
			validSubs->right = current->right->left;
			current->right->left = nullptr;
			current->right->left = current->left;
			/*if (parent == current)
				parent = current->right;*/
			if (parent->left == current)
				parent->left = current->right;
			if (parent->right == current)
				parent->right = current->right;
		}
		delete current;
		count--;
		return true;
	}
	if (current->data > val)
		return removeElement(current, current->left, val);
	else
		return removeElement(current, current->right, val);
}

template<typename T>
bool BinaryTree<T>::deleteValue(const T& value)
{
	return this->removeElement(NULL, root, value);
}

template <typename T>
std::ostream& operator<<(std::ostream& out, const BinaryTree<T>& temp)
{
	output(out, temp.root, 0);
	return out;
}
<commit_msg>Create matrix.hpp<commit_after>#include <iostream>
#include <string>
#include <fstream>
#include <cstdint>

using namespace std;

template <typename T>
struct Node
{
	Node *left;
	Node *right;
	T data;
};

template <typename T>
class BinaryTree;

template <typename T>
std::ostream& operator<<(std::ostream&, const BinaryTree<T>&);

template <typename T>
class BinaryTree
{
private:
	Node<T>*root;
	int count = 0;
public:
	BinaryTree();
	~BinaryTree();
	Node<T>* root_();
	unsigned int getCount()const;
	Node<T> *findNode(const T&, Node<T>*)const;
	void insertNode(const T&x);
	void deleteNode(Node<T>* temp);
	bool removeElement(Node<T>* parent, Node<T>* current, const T& val);
	bool deleteValue(const T& value);
	void write(const std::string& filename)const;
	friend std::ostream& operator<<<>(std::ostream&, const BinaryTree<T>&);
};

template <typename T>
BinaryTree<T>::BinaryTree()
{
	root = nullptr;
}

template<typename T>
Node<T>* BinaryTree<T>::root_()
{
	return root;
}

template <typename T>
BinaryTree<T>::~BinaryTree()
{
	deleteNode(root);
}

template <typename T>
unsigned int BinaryTree<T>::getCount()const
{
	return count;
}

template<typename T>
Node<T>* BinaryTree<T>::findNode(const T& data, Node<T>* temp) const
{
	if (temp == 0 || data == temp->data)
		return temp;
	if (data > temp->data)
		return findNode(data, temp->right);
	else
		return findNode(data, temp->left);
}

template<typename T>
void BinaryTree<T>::insertNode(const T&x)
{
	if (findNode(x, root_())) return;
	Node<T>* Tree = new Node<T>;
	Tree->data = x;
	Tree->left = Tree->right = 0;
	Node<T>* buff = root;
	Node<T>* temp = root;
	while (temp)
	{
		buff = temp;
		if (x < temp->data)
			temp = temp->left;
		else
			temp = temp->right;
	}
	if (!buff)
		root = Tree;
	else
	{
		if (x < buff->data)
			buff->left = Tree;
		else
			buff->right = Tree;
	}
	++count;
}

template<typename T>
void BinaryTree<T>::write(const std::string& filename)const
{
	ofstream file_1(filename);
	file_1 << count << "\t";
	output(file_1, root);
	file_1.close();
}

template<typename T>
void BinaryTree<T>::deleteNode(Node<T>* temp)
{
	if (!temp)
		return;
	if (temp->left)
	{
		deleteNode(temp->left);
		temp->left = nullptr;
	}

	if (temp->right)
	{
		deleteNode(temp->right);
		temp->right = nullptr;
	}
	delete temp;
}

template <typename T>
std::ostream& output(std::ostream& out, const Node<T>* node, unsigned int level)
{
	if (!node)
		return out;
	output(out, node->right, level + 1);
	for (unsigned int i = 0; i < level; i++)
		out << "\t";
	out << node->data << std::endl;
	output(out, node->left, level + 1);
	return out;
}

template<typename T>
bool BinaryTree<T>::removeElement(Node<T>* parent, Node<T>* current, const T& val)
{
	if (!current) return false;
	if (current->data == val)
	{
		if (current->left == NULL || current->right == NULL) {
			Node<T>* temp = current->left;
			if (current->right) temp = current->right;
			if (parent) {
				if (parent->left == current) {
					parent->left = temp;
				}
				else {
					parent->right = temp;
				}
			}
			else {
				this->root = temp;
			}
			delete current;
		}
		/*else {
			Node<T>* validSubs = current->right;
			while (validSubs->left) {
				validSubs = validSubs->left;
			}
			T temp = current->data;
			current->data = validSubs->data;
			validSubs->data = temp;
			return removeElement(current, current->right, temp);
		}*/
		else {
			Node<T>* validSubs = current->left;
			while (validSubs->right) {
				validSubs = validSubs->right;
			}
			validSubs->right = current->right->left;
			current->right->left = nullptr;
			current->right->left = current->left;
			if (parent == current)
				parent = current->right;
			if (parent->left == current)
				parent->left = current->right;
			if (parent->right == current)
				parent->right = current->right;
		}
		//delete current;
		count--;
		return true;
	}
	if (current->data > val)
		return removeElement(current, current->left, val);
	else
		return removeElement(current, current->right, val);
}

template<typename T>
bool BinaryTree<T>::deleteValue(const T& value)
{
	return this->removeElement(NULL, root, value);
}

template <typename T>
std::ostream& operator<<(std::ostream& out, const BinaryTree<T>& temp)
{
	output(out, temp.root, 0);
	return out;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2020 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <gtest/gtest.h>

#include "call_type.hh"

TEST(AddrCallType, Sum)
{
}
<commit_msg>util: Add a unit test for the "addr" call type in the m5 util.<commit_after>/*
 * Copyright 2020 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <gtest/gtest.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>

#include <csetjmp>
#include <csignal>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>

#include <gem5/asm/generic/m5ops.h>

#include "args.hh"
#include "call_type.hh"
#include "dispatch_table.hh"
#include "m5_mmap.h"

class DefaultCallType : public CallType
{
  private:
    DispatchTable dt;

  public:
    DefaultCallType() : CallType("default") {}

    bool initCalled = false;
    void init() override { initCalled = true; }

    bool isDefault() const override { return true; }
    void printDesc(std::ostream &os) const override {}
    const DispatchTable &getDispatch() const override { return dt; }
};

DefaultCallType defaultCallType;

#if defined(M5OP_ADDR)
const bool DefaultAddrDefined = true;
constexpr uint64_t DefaultAddress = M5OP_ADDR;
#else
const bool DefaultAddrDefined = false;
constexpr uint64_t DefaultAddress = 0;
#endif

class AddrCallTypeTest : public testing::Test
{
  protected:
    CallType *ct = nullptr;

    void
    SetUp() override
    {
        m5_mmap_dev = "/dev/zero";
        m5op_addr = 2;
    }

    void
    TearDown() override
    {
        unmap_m5_mem();
    }
};

TEST_F(AddrCallTypeTest, EmptyArgs)
{
    // Addr should not be selected if there are no arguments.
    Args empty({});
    defaultCallType.initCalled = false;
    ct = CallType::detect(empty);
    EXPECT_EQ(ct, &defaultCallType);
    EXPECT_TRUE(defaultCallType.initCalled);
}

TEST_F(AddrCallTypeTest, OneArgMismatch)
{
    // Addr should not be selected if --addr isn't the first argument.
    Args one_arg({"one"});
    defaultCallType.initCalled = false;
    ct = CallType::detect(one_arg);
    EXPECT_EQ(ct, &defaultCallType);
    EXPECT_TRUE(defaultCallType.initCalled);
    EXPECT_EQ(one_arg.size(), 1);
}

TEST_F(AddrCallTypeTest, OneArgSelected)
{
    // Addr should be selected if --addr is the first argument.
    Args selected({"--addr=3"});
    defaultCallType.initCalled = false;
    ct = CallType::detect(selected);
    EXPECT_NE(ct, &defaultCallType);
    EXPECT_NE(ct, nullptr);
    EXPECT_FALSE(defaultCallType.initCalled);
    EXPECT_EQ(m5op_addr, 3);
}

TEST_F(AddrCallTypeTest, SplitSelected)
{
    Args split({"--addr", "3"});
    defaultCallType.initCalled = false;
    ct = CallType::detect(split);
    EXPECT_NE(ct, &defaultCallType);
    EXPECT_NE(ct, nullptr);
    EXPECT_FALSE(defaultCallType.initCalled);
    EXPECT_EQ(m5op_addr, 3);
}

TEST_F(AddrCallTypeTest, OneArgSelectedExtra)
{
    Args selected_extra({"--addr=3", "foo"});
    defaultCallType.initCalled = false;
    ct = CallType::detect(selected_extra);
    EXPECT_NE(ct, &defaultCallType);
    EXPECT_NE(ct, nullptr);
    EXPECT_FALSE(defaultCallType.initCalled);
    EXPECT_EQ(m5op_addr, 3);
}

TEST_F(AddrCallTypeTest, SplitSelectedExtra)
{
    Args split_extra({"--addr", "3", "foo"});
    defaultCallType.initCalled = false;
    ct = CallType::detect(split_extra);
    EXPECT_NE(ct, &defaultCallType);
    EXPECT_NE(ct, nullptr);
    EXPECT_FALSE(defaultCallType.initCalled);
    EXPECT_EQ(m5op_addr, 3);
}

TEST_F(AddrCallTypeTest, SupersetOneArg)
{
    // Nothing should be selected if an argument starts with --addr which is
    // followed by something other than '=' and then a number.
    Args no_equal({"--address"});
    defaultCallType.initCalled = false;
    ct = CallType::detect(no_equal);
    EXPECT_EQ(ct, nullptr);
    EXPECT_FALSE(defaultCallType.initCalled);
    EXPECT_EQ(m5op_addr, 2);
}

TEST_F(AddrCallTypeTest, NonNumberAddr)
{
    Args no_number({"--addr=foo"});
    defaultCallType.initCalled = false;
    ct = CallType::detect(no_number);
    EXPECT_EQ(ct, nullptr);
    EXPECT_FALSE(defaultCallType.initCalled);
    EXPECT_EQ(m5op_addr, 2);
}

TEST_F(AddrCallTypeTest, DetectDefaultAddr)
{
    if (!DefaultAddrDefined)
        return;

    // Verify that the default address is set up in m5op_addr.
    Args noaddr({"--addr"});
    defaultCallType.initCalled = false;
    m5op_addr = DefaultAddress;
    ct = CallType::detect(noaddr);
    EXPECT_NE(ct, &defaultCallType);
    EXPECT_NE(ct, nullptr);
    EXPECT_FALSE(defaultCallType.initCalled);
    EXPECT_EQ(m5op_addr, DefaultAddress);
}

TEST_F(AddrCallTypeTest, DetectDefaultAddrExtra)
{
    if (!DefaultAddrDefined)
        return;

    Args noaddr_foo({"--addr", "foo"});
    defaultCallType.initCalled = false;
    m5op_addr = DefaultAddress;
    ct = CallType::detect(noaddr_foo);
    EXPECT_NE(ct, &defaultCallType);
    EXPECT_NE(ct, nullptr);
    EXPECT_FALSE(defaultCallType.initCalled);
    EXPECT_EQ(m5op_addr, DefaultAddress);
}

TEST_F(AddrCallTypeTest, DetectNoDefault)
{
    if (DefaultAddrDefined)
        return;

    // Verify that the address must be specified since there's no default.
    Args noaddr({"--addr"});
    defaultCallType.initCalled = false;
    m5op_addr = DefaultAddress + 1;
    ct = CallType::detect(noaddr);
    EXPECT_EQ(ct, nullptr);
    EXPECT_FALSE(defaultCallType.initCalled);
    EXPECT_EQ(m5op_addr, DefaultAddress + 1);
}

TEST_F(AddrCallTypeTest, DetectNoDefaultExtra)
{
    if (DefaultAddrDefined)
        return;

    Args noaddr_foo({"--addr", "foo"});
    defaultCallType.initCalled = false;
    m5op_addr = DefaultAddress + 1;
    ct = CallType::detect(noaddr_foo);
    EXPECT_EQ(ct, nullptr);
    EXPECT_FALSE(defaultCallType.initCalled);
    EXPECT_EQ(m5op_addr, DefaultAddress + 1);
}

TEST_F(AddrCallTypeTest, NotFirstArg)
{
    // Addr should not be selected if --addr isn't first.
    Args not_first({"foo", "--addr"});
    defaultCallType.initCalled = false;
    ct = CallType::detect(not_first);
    EXPECT_EQ(ct, &defaultCallType);
    EXPECT_TRUE(defaultCallType.initCalled);
    EXPECT_EQ(not_first.size(), 2);
}

sigjmp_buf interceptEnv;
siginfo_t interceptSiginfo;

void
sigsegv_handler(int sig, siginfo_t *info, void *ucontext)
{
    std::memcpy(&interceptSiginfo, info, sizeof(interceptSiginfo));
    siglongjmp(interceptEnv, 1);
}

const uint64_t MmapPhysAddr = 0x1000000;

// A class to create and clean up a sparse temporary file of a given size.
class TempFile
{
  private:
    size_t _size;
    int fd;
    std::string _path;

  public:
    TempFile(size_t _size) : _size(_size)
    {
        // Generate a temporary filename.
        char *tmp_name = strdup("/tmp/addr.test.XXXXXXXX");
        fd = mkstemp(tmp_name);
        _path = tmp_name;
        free(tmp_name);

        // Make the file the appropriate length.
        assert(!ftruncate(fd, _size));
    };

    ~TempFile()
    {
        unlink(path().c_str());
        close(fd);
    }

    const std::string &path() const { return _path; }
};

// Sparse dummy mmap file if we're not in gem5.
TempFile mmapDummyFile(MmapPhysAddr * 2);

void
verify_mmap()
{
    // Look for the proc file that lists all our mmap-ed files.
    pid_t pid = getpid();

    std::ostringstream os;
    os << "/proc/" << pid << "/maps";
    auto maps_path = os.str();

    if (access(maps_path.c_str(), R_OK) == -1) {
        std::cout << "Unable to access " << maps_path <<
            ", can't verify mmap." << std::endl;
        return;
    }

    // Verify that the right area is mmap-ed.
    std::ifstream maps(maps_path);
    EXPECT_TRUE(maps);

    uint64_t start, end, offset, inode;
    std::string path, permissions, device;

    std::istringstream line_ss;
    bool found = false;
    while (!maps.eof()) {
        std::string line;
        if (getline(maps, line).fail()) {
            std::cout << "Error reading from \"" << maps_path << "\"." <<
                std::endl;
            return;
        }

        line_ss.str(line);

        line_ss >> std::hex >> start >> std::dec;

        char c;
        line_ss.get(c);
        if (c != '-') {
            std::cout << "Badly formatted maps line." << std::endl;
            continue;
        }

        // Is this the mapping we're interested in?
        if (start == (uintptr_t)m5_mem) {
            found = true;
            break;
        }
    }

    if (maps.eof() && !found) {
        std::cout << "Did not find entry for temp file \"" <<
            mmapDummyFile.path() << "\" in \"" << maps_path <<
            "\"." << std::endl;
        ADD_FAILURE() << "No mapping for our mmapped file.";
        return;
    }

    // We found our mapping. Try to extract the remaining fields.
    line_ss >> std::hex >> end >> std::dec;
    line_ss >> permissions;
    line_ss >> std::hex >> offset >> std::dec;
    line_ss >> device;
    line_ss >> inode;

    // Everything left on the line goes into "path".
    getline(line_ss, path);

    // Strip off whitespace on either end of the path.
    const char *ws = " \t\n\r\f\v";
    // If nothing would be left, don't bother.
    if (path.find_first_not_of(ws) != std::string::npos) {
        path.erase(path.find_last_not_of(ws) + 1);
        path.erase(0, path.find_first_not_of(ws));
    }

    // Use stat to make sure this is the right file, in case the path
    // strings are immaterially different.
    struct stat stata, statb;
    EXPECT_EQ(stat(path.c_str(), &stata), 0);
    EXPECT_EQ(stat(mmapDummyFile.path().c_str(), &statb), 0);
    EXPECT_EQ(stata.st_dev, statb.st_dev);
    EXPECT_EQ(stata.st_ino, statb.st_ino);

    // Make sure the mapping is in the right place and the right size.
    EXPECT_EQ(end - start, 0x10000);
    EXPECT_EQ(offset, MmapPhysAddr);
}

TEST(AddrCallType, Sum)
{
    // Determine if we're running within gem5 by checking whether a flag is
    // set in the environment.
    bool in_gem5 = (std::getenv("RUNNING_IN_GEM5") != nullptr);
    if (in_gem5)
        std::cout << "In gem5, m5 ops should work." << std::endl;
    else
        std::cout << "Not in gem5, m5 ops won't work." << std::endl;

    // Get the addr call type, which is in an anonymous namespace. Set the
    // address to a well known constant that's nicely aligned.
    Args args({"--addr=0x1000000"});
    if (!in_gem5) {
        // Change the file to be mmap-ed to something not dangerous, but only
        // if we're not in gem5. Otherwise we'll need this to really work.
        m5_mmap_dev = mmapDummyFile.path().c_str();
    }
    CallType *addr_call_type = CallType::detect(args);
    EXPECT_NE(addr_call_type, nullptr);
    EXPECT_EQ(m5op_addr, MmapPhysAddr);

    verify_mmap();

    // Get the dispatch table associated with it.
    const auto &dt = addr_call_type->getDispatch();

    // If we're in gem5, then we should be able to run the "sum" command.
    if (in_gem5) {
        EXPECT_EQ((*dt.m5_sum)(2, 2, 0, 0, 0, 0), 4);
        return;
    }

    // If not, then we'll need to try to catch the fall out from trying to run
    // an m5 op and verify that what we were trying looks correct.

    // Block access to the page that was mapped.
    mprotect(m5_mem, 0x10000, 0);

    struct sigaction sigsegv_action;
    std::memset(&sigsegv_action, 0, sizeof(sigsegv_action));
    sigsegv_action.sa_sigaction = &sigsegv_handler;
    sigsegv_action.sa_flags = SA_SIGINFO | SA_RESETHAND;

    struct sigaction old_sigsegv_action;

    sigaction(SIGSEGV, &sigsegv_action, &old_sigsegv_action);

    if (!sigsetjmp(interceptEnv, 1)) {
        (*dt.m5_sum)(2, 2, 0, 0, 0, 0);
        sigaction(SIGSEGV, &old_sigsegv_action, nullptr);
        ADD_FAILURE() << "Didn't die when attempting to run \"sum\".";
        return;
    }

    // Restore access to the page that was mapped.
    mprotect(m5_mem, 0x10000, PROT_READ | PROT_WRITE);

    // Back from siglongjump.
    auto &info = interceptSiginfo;

    EXPECT_EQ(info.si_signo, SIGSEGV);
    EXPECT_EQ(info.si_code, SEGV_ACCERR);

    uintptr_t access_addr = (uintptr_t)info.si_addr;
    uintptr_t virt_addr = (uintptr_t)m5_mem;

    // Verify that the address was in the right area.
    EXPECT_LT(access_addr, virt_addr + 0x10000);
    EXPECT_GE(access_addr, virt_addr);

    // Extract the func number.
    uintptr_t offset = access_addr - virt_addr;
    int func = (offset & 0xff00) >> 8;
    EXPECT_EQ(func, M5OP_SUM);
}
<|endoftext|>