Wątek zablokowany 2016-05-26 16:14 przez furious programming.

Jak wprowadzic naglowek okreslajacy rozmiar?

0

hej!
zwracam sie do was z takim pytaniem, jak wprowadzic naglowek konca paczki okreslajacy jej rozmiar?
bez niego kazda paczka musi byc przeszukiwana bajt po bajcie w poszukiwaniu naglowka w stylu xxx: yyy
co kompletnie kladzie wydajnosc / z gory dziekuje :)

przyklad

"piekarz: wstaw: 9; bulki janka"
"piekarz: wyjmij: 27; bagietki z pieca"

sizeof ("bulki janka") =9
sizeof ("bagietki z pieca") =27

wtedy jedynie sprawdzam:

  1. target: "piekarz: wstaw",
  2. dlugosc wiadomosci, bym wiedzial ile kolejnych bajtow nalezy do paczki
  3. sama wiadomosc, nastepnie wysylam odpowiednio / najlepiej przy zachowaniu wysokiej wydajnosci kodu

ps. w odniesieniu do: http://melpon.org/wandbox/permlink/GqVYYYPoXZKOv5Eh / @spartanPAGE

1

Tak na szybko:

(Przypomnienie: używany mock socketa)

#pragma once

#include <iostream>
#include <vector>
#include <string>

template<typename Socket>
auto fetch_next(Socket &sock) {
    return sock.fetch_next();
}

namespace mock {
    class socket {
    public:
        using data_type = std::string;
        using send_calls_type = std::vector<data_type>;
        
        socket(send_calls_type &&scalls):
            send_calls(std::rbegin(scalls), std::rend(scalls)) {}
        
        data_type fetch_next() {
            return send_calls.size()?
                pop() : data_type{};
        }
    private:
        data_type pop() {
            auto result = send_calls.back();
            send_calls.pop_back();
            return result;
        }
        send_calls_type send_calls;
    };
}

Pakowanie danych do komunikacji (communication.hpp):

#pragma once

#include <vector>
#include <string>

#include <boost/type_index.hpp>

namespace communication {
    using strings = std::vector<std::string>;
    
    struct package {
        std::string identifier;
        strings data;
    };
    
    std::string to_csv(package const &pkg) {
        std::string result = pkg.identifier;
        for(auto &&el: pkg.data) {
            result += ",\""+el+"\"";
        }
        return result;
    }
    
    template<typename T>
    package make_package(std::string const &id, T const &msg) {
        return package {
            id, msg.as_strings()
        };
    }
    
    template<typename T>
    package to_package(T const &msg) {
        return make_package(
            boost::typeindex::type_id<T>().pretty_name(), msg);
    }
}

main.cpp:

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <functional>

#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/classification.hpp>

#include "socket.hpp"
#include "communication.hpp"

namespace command {
    struct unit {
        std::string who, what, details;
        
        static unit from(communication::strings const strings) {
            return { strings[0], strings[1], strings[2] };
        }
        
        communication::strings as_strings() const {
            return { who, what, details };
        }
    };
    
    struct system {
        std::string function, input;
        
        static system from(communication::strings const strings) {
            return { strings[0], strings[1] };
        }
        
        communication::strings as_strings() const {
            return { function, input };
        }
    };
}

std::vector<std::string> split_csv(std::string const &csv) {
    std::vector<std::string> result;
    boost::split(result, csv, boost::is_any_of(","), boost::token_compress_on);
    return result;
}

std::string without_quotes(std::string const &str) {
    return str.at(0) == '\"'?
        std::string(std::begin(str)+1, std::end(str)-1) : str;
}

void inspect(std::string const &data) {
    std::cout << "##INSPECTION: BEGIN\n" << "(raw data:)\n" << data << "\n";
    auto splitted = split_csv(data);
    std::cout << "(splitted:)\n";
    for(auto el: split_csv(data)) {
        std::cout << without_quotes(el) << "\n";
    }
    std::cout << "##INSPECTION: END\n";
}

using handler = std::function<void(communication::strings const &)>;

using handlers_map = std::unordered_map<std::string, handler>;

void handle(handlers_map const &handlers, std::string const &data) {
    auto strings = split_csv(data);
    handlers.at(strings[0])
        (communication::strings(std::begin(strings)+1, std::end(strings)));
}

int main() {
    using namespace communication;
    mock::socket socket {{
        to_csv(to_package(command::unit {
            "piekarz", "wstaw 9", "bulki janka"
        })),
        to_csv(to_package(command::unit {
            "piekarz", "wyjmij 27", "bagietki z pieca"
        })),
        to_csv(to_package(command::system {
            "print", "Hello World!"
        }))
    }};
    
    handlers_map handlers {
        {{"command::unit"}, [](communication::strings const &strings) {
            auto cmd = command::unit::from(strings);
            std::cout << "\n>> todo: recognize and launch unit command\n";
        }},
        {{"command::system"}, [](communication::strings const &strings) {
            auto cmd = command::system::from(strings);
            std::cout << "\n>> todo: recognize and launch system command\n";
        }}
    };
    
    std::string data;
    while((data = fetch_next(socket)).size()){
        inspect(data);
        handle(handlers, data);
        std::cout << std::endl;
    }
    
    return 0;
}

link: http://melpon.org/wandbox/permlink/g1hdapMODrPrN9cA

output:

##INSPECTION: BEGIN
(raw data:)
command::unit,"piekarz","wstaw 9","bulki janka"
(splitted:)
command::unit
piekarz
wstaw 9
bulki janka
##INSPECTION: END

>> todo: recognize and launch unit command

##INSPECTION: BEGIN
(raw data:)
command::unit,"piekarz","wyjmij 27","bagietki z pieca"
(splitted:)
command::unit
piekarz
wyjmij 27
bagietki z pieca
##INSPECTION: END

>> todo: recognize and launch unit command

##INSPECTION: BEGIN
(raw data:)
command::system,"print","Hello World!"
(splitted:)
command::system
print
Hello World!
##INSPECTION: END

>> todo: recognize and launch system command

To, co powinieneś teraz zrobić, to napisać obsługę rozpoznanych komend (operując na gotowych command::unit i command::system lub na czymkolwiek co sobie dorzucisz)

PS. wstaw 9 możesz przetrawić przy pomocy stringstream
PPS. Jestem dopiero w połowie 3 sezonu :P

1 użytkowników online, w tym zalogowanych: 0, gości: 1