<commit_before>// vim:syntax=lpc
// put that somewhere else.. maybe
//
#include <debug.h>

class Dummy(mixed...params) { }

Packet reply(Packet m, string|void mc, string|void data, mapping(string:mixed)|void vars) {
    Packet t = Packet(mc, data, vars);

    if (has_index(m->vars, "_tag"))
	t->vars["_tag_reply"] = m->vars["_tag"];

    return t;
}

class Packet {
    string mc, cache;
    mapping (string:mixed) vars;
    string data;

    void create(string|void m, mapping(string:mixed)|void v, string|void d) {
	if (m) mc = m;
	data = d || "";
	vars = v || ([ ]);
    }

    mixed cast(string type) {
	switch(type) {
	case "string":
	    return cache || (cache = .module.render(this_object()));
	case "String.Buffer":
	    return String.Buffer() + (string)this;
	default:
	    return UNDEFINED;
	}
    }

    string _sprintf(int format) {
	switch (format) {
	    case 'O':
#if defined(DEBUG) && DEBUG < 3
		return sprintf("PSYC.Packet(%O, %O)", mc, vars);
#else
		return sprintf("PSYC.Packet(%O)", mc);
#endif
	    case 's':
		return (string)this;
	}
    }

    PSYC.Packet reply(string|void mc, mapping(string:mixed)|void v, string|void d) {
	PSYC.Packet m = PSYC.Packet(mc, v, d);

	if (has_index(vars, "_tag") && sizeof(vars["_tag"])) {
	    m["_tag_reply"] = vars["_tag"]; 
	}

	return m;
    }

    mixed `[]=(mixed id, mixed val) {
	cache = UNDEFINED;
	return vars[id] = val;
    }

    mixed `->=(string id, mixed val) {
	cache = UNDEFINED;
	return ::`->=(id, val);
    }

    mixed `[](mixed id) {
	return vars[id];
    }
}

#if 0
// evil parser
string psyctext(PSYC.Packet m) {
    String.Buffer buf = String.Buffer(); 

    string data = m->data;
    
    int opened;
    int start, stop;

    while (stop < sizeof(data)-1) {
	start = stop;
	if (opened) {
	    stop = search(data, "]", start);
	} else {
	    stop = search(data, "[", start);
	}

	if (stop == -1 || sizeof(data)-1 <= stop+1) {
	    buf->add(data[start..]);
	    break;
	}

	if (opened && data[start+1] == '_' <commit_msg>(yet) unused and unfinished adapter class to handle the target vs. server discrepancy (multiple servers can be the drain for a target - think of load balancing and backup server strategies)<commit_after>// vim:syntax=lpc
// put that somewhere else.. maybe
//
#include <debug.h>

class Dummy(mixed...params) { }

Packet reply(Packet m, string|void mc, string|void data, mapping(string:mixed)|void vars) {
    Packet t = Packet(mc, data, vars);

    if (has_index(m->vars, "_tag"))
	t->vars["_tag_reply"] = m->vars["_tag"];

    return t;
}

class Packet {
    string mc, cache;
    mapping (string:mixed) vars;
    string data;

    void create(string|void m, mapping(string:mixed)|void v, string|void d) {
	if (m) mc = m;
	data = d || "";
	vars = v || ([ ]);
    }

    mixed cast(string type) {
	switch(type) {
	case "string":
	    return cache || (cache = .module.render(this_object()));
	case "String.Buffer":
	    return String.Buffer() + (string)this;
	default:
	    return UNDEFINED;
	}
    }

    string _sprintf(int format) {
	switch (format) {
	    case 'O':
#if defined(DEBUG) && DEBUG < 3
		return sprintf("PSYC.Packet(%O, %O)", mc, vars);
#else
		return sprintf("PSYC.Packet(%O)", mc);
#endif
	    case 's':
		return (string)this;
	}
    }

    PSYC.Packet reply(string|void mc, mapping(string:mixed)|void v, string|void d) {
	PSYC.Packet m = PSYC.Packet(mc, v, d);

	if (has_index(vars, "_tag") && sizeof(vars["_tag"])) {
	    m["_tag_reply"] = vars["_tag"]; 
	}

	return m;
    }

    mixed `[]=(mixed id, mixed val) {
	cache = UNDEFINED;
	return vars[id] = val;
    }

    mixed `->=(string id, mixed val) {
	cache = UNDEFINED;
	return ::`->=(id, val);
    }

    mixed `[](mixed id) {
	return vars[id];
    }
}

// this is an intermediate object which tries to keep a circuit to a certain
// target open.
// multiple of this adapters may share the same circuit.
// however, if a circuit breaks and can't be reestablished, 
// adapters that once shared a circuit may end up in using different circuits
// (to different servers).
class Adapter { // TODO:: change that name!!
    MMP.Utils.Queue q;
    MMP.Circuit circuit;
    MMP.Utils.DNS.SRVReply cres;
    PSYC.Server server;
    function check_out;
    // following to will be needed when a circuit breaks and can't be
    // reestablished
    string targethost;
    int targetport;

    void create(MMP.Uniform target, PSYC.Server srv, function co) {
	targethost = target->host;
	targetport = target->port;

	server = srv;
	check_out = co;

	init();
    }

    void init() {
	int port = targetport;
	if (MMP.Utils.Net.is_ip(targethost) && !port) port = 4404;

	if (port) {
	    connect_host(targethost, port);
	} else {
	    connect_srv(targethost);
	}
    }

    void on_connect(MMP.Circuit c) {
	if (c) {
	    circuit = c;

	    if (q) {
		destruct(cres);
		// very temporary solution. we'll need to maintain our own queue
		// and only advertise msg-requests to the circuit, which will
		// then shift the messages here.
		while (!q->isEmpty()) {
		    c->msg(q->shift());
		}

		destruct(q);
	    }
	} else {
	    if (cres) {
		srv_step();
	    } else {
		// TODO:: try alternatives (srv, multiple a rr), eventually
		// error.
	    }
	}
    }


    void connect_ip(string ip, int port) {
	server->circuit_to(ip, port, on_connect);
    }

    void connect_host(string host, int port) {
	void dispatch(string query, string ip) {
	    if (ip) {
		connect_ip(ip, port);
	    } else {
		// TODO:: error
	    }
	};

	if (MMP.Utils.Net.is_ip(host)) {
	    connect_ip(host, port);
	} else {
	    // TODO:: resolve in a way that gives us multiple records.
	    Protocols.DNS.async_host_to_ip(host, dispatch);
	}
    }

    void srv_step() {
	if (cres->has_next()) {
	    mapping m = cres->next();

	    connect_host(m->target, m->port);
	} else {
	    destruct(cres);
	    // TODO:: there was at least one srv-host, not reachable, so we
	    // can't reach the target and therefore need to error!
	}
    }

    void connect_srv(string host) {
	void srvcb(string query, MMP.Utils.DNS.SRVReply|int result) {
	    if (objectp(result)) {
		if (result->has_next()) {
		    if (has_value(result->result->target, ".")) {
			// no psyc offered. error all queued packages, error
			// and destruct.
		    } else {
			cres = result;
			srv_step();
		    }
		} else {
		    connect_host(host, 4404);
		}
	    }
	};

	MMP.Utils.DNS.async_srv("psyc-server", "tcp", host, srvcb);
    }
}

#if 0
// evil parser
string psyctext(PSYC.Packet m) {
    String.Buffer buf = String.Buffer(); 

    string data = m->data;
    
    int opened;
    int start, stop;

    while (stop < sizeof(data)-1) {
	start = stop;
	if (opened) {
	    stop = search(data, "]", start);
	} else {
	    stop = search(data, "[", start);
	}

	if (stop == -1 || sizeof(data)-1 <= stop+1) {
	    buf->add(data[start..]);
	    break;
	}

	if (opened && data[start+1] == '_' 
{'fraction_non_alphanumeric': 0.1603595766275192, 'fraction_numerical': 0.003189792663476874, 'mean_word_length': 2.8089453340695747, 'pattern_counts': {'":': 4, '<': 11, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5970108', 'n_tokens_mistral': 2647, 'n_tokens_neox': 2461, 'n_words': 678}