Untitled

mail@pastecode.io avatar
unknown
plain_text
2 years ago
6.2 kB
0
Indexable
Never
#include <fstream>

#include "serialization.h"

namespace serialize {

void Serializator::AddTransportCatalogue(const TransportCatalogue &catalogue) {
    SaveStops(catalogue);
    SaveRoutes(catalogue);
    SaveDistances(catalogue);
}

bool Serializator::Serialize() {
    std::ofstream ofs(settings_.path, std::ios::binary);
    if (!ofs.is_open ()) {
            return false;
    }
    proto_catalogue_.SerializeToOstream(&ofs);
    Clear();
    return true;
}

bool Serializator::Deserialize(TransportCatalogue &catalogue) {
    std::ifstream ifs(settings_.path, std::ios::binary);
    if (!ifs.is_open() || !proto_catalogue_.ParseFromIstream(&ifs)) {
        return false;
    }

    LoadStops(catalogue);
    LoadRoutes(catalogue);
    LoadDistances(catalogue);

    Clear();
    return true;
}

void Serializator::Clear() noexcept {
    proto_catalogue_.Clear();
    stop_name_by_id_.clear();
    stop_id_by_name_.clear();
    route_name_by_id_.clear();
    route_id_by_name_.clear();
}

void Serializator::SaveStops(const TransportCatalogue &catalogue) {
    auto &stops = catalogue.GetStops();
    uint32_t id = 0;
    for (auto [name, stop] : stops) {
        transport_catalogue_serialize::Stop p_stop;
        p_stop.set_id(id);
        p_stop.set_name(stop->name);
        *p_stop.mutable_coordinates() = MakeProtoCoordinates(stop->coordinate);
        stop_id_by_name_.insert({name, id++});
        *proto_catalogue_.mutable_catalogue()->add_stops() = std::move(p_stop);
    }
}

void Serializator::SaveRoutes(const TransportCatalogue &catalogue) {
    auto &routes = catalogue.GetRoutes();
    uint32_t id = 0;
    for (auto [name, route] : routes) {
        transport_catalogue_serialize::Route p_route;
        p_route.set_id(id);
        p_route.set_name(route->name);
        p_route.set_type(MakeProtoRouteType(route->route_type));
        SaveRouteStops(*route, p_route);
        route_id_by_name_.insert({name, id++});
        *proto_catalogue_.mutable_catalogue()->add_routes() = std::move(p_route);
    }
}

void Serializator::SaveRouteStops(const domain::Route &route,
                                  transport_catalogue_serialize::Route &p_route) {
    for (auto stop : route.stops) {
        p_route.add_stop_ids(stop_id_by_name_.at(stop->name));
    }
}

void Serializator::SaveDistances(const TransportCatalogue &catalogue) {
    auto &distances = catalogue.GetDistances();
    for (auto &[stop1, stops] : distances) {
        for(auto [stop2, distance] : stops) {
            transport_catalogue_serialize::Distance p_distance;
            p_distance.set_stop_id_from(stop_id_by_name_.at(stop1));
            p_distance.set_stop_id_to(stop_id_by_name_.at(stop2));
            p_distance.set_distance(distance);
            *proto_catalogue_.mutable_catalogue()->add_distances() = std::move(p_distance);
        }
    }
}

void Serializator::LoadStops(TransportCatalogue &catalogue) {
    auto stops_count = proto_catalogue_.catalogue().stops_size();
    for (int i = 0; i < stops_count; ++i) {
        auto &p_stop = proto_catalogue_.catalogue().stops(i);
        catalogue.AddStop(p_stop.name(), MakeCoordinates(p_stop.coordinates()));
        stop_name_by_id_.insert({p_stop.id(), p_stop.name()});
    }
}

void Serializator::LoadRoutes(TransportCatalogue &catalogue) {
    auto routes_count = proto_catalogue_.catalogue().routes_size();
    for (int i = 0; i < routes_count; ++i) {
        auto &p_route = proto_catalogue_.catalogue().routes(i);
        LoadRoute(catalogue, p_route);
        route_name_by_id_.insert({p_route.id(), p_route.name()});
    }
}

void Serializator::LoadRoute(TransportCatalogue &catalogue,
                             const transport_catalogue_serialize::Route &p_route) const {
    auto stops_count = p_route.stop_ids_size();
    std::vector<std::string> stops;
    stops.reserve(stops_count);
    for(int i = 0; i < stops_count; ++i) {
        auto stop_name = stop_name_by_id_.at(p_route.stop_ids(i));
        stops.push_back(std::string(stop_name));
    }
    catalogue.AddRoute(p_route.name(), MakeRouteType(p_route.type()), stops);
}

void Serializator::LoadDistances(TransportCatalogue &catalogue) const {
    auto distances_count = proto_catalogue_.catalogue().distances_size();
    for (int i = 0; i < distances_count; ++i) {
        auto &p_distance = proto_catalogue_.catalogue().distances(i);
        auto stop_from = std::string(stop_name_by_id_.at(p_distance.stop_id_from()));
        auto stop_to = std::string(stop_name_by_id_.at(p_distance.stop_id_to()));
        catalogue.SetDistance(stop_from, stop_to, p_distance.distance());
    }
}

transport_catalogue_serialize::Coordinates
Serializator::MakeProtoCoordinates(const geo::Coordinates &coordinates) {
    transport_catalogue_serialize::Coordinates p_coordinates;
    p_coordinates.set_lat(coordinates.lat);
    p_coordinates.set_lng(coordinates.lng);
    return p_coordinates;
}

geo::Coordinates
Serializator::MakeCoordinates(const transport_catalogue_serialize::Coordinates &p_coordinates) {
    geo::Coordinates coordinates;
    coordinates.lat = p_coordinates.lat();
    coordinates.lng = p_coordinates.lng();
    return coordinates;
}

transport_catalogue_serialize::RouteType
Serializator::MakeProtoRouteType(domain::RouteType route_type) {
    using ProtoRouteType = transport_catalogue_serialize::RouteType;
    ProtoRouteType type;
    switch (route_type) {
    case domain::RouteType::LINEAR :
        type = ProtoRouteType::LINEAR;
        break;
    case domain::RouteType::CIRCLE :
        type = ProtoRouteType::CIRCLE;
        break;
    default:
        type = ProtoRouteType::UNKNOWN;
        break;
    }
    return type;
}

domain::RouteType
Serializator::MakeRouteType(transport_catalogue_serialize::RouteType p_route_type) {
    using ProtoRouteType = transport_catalogue_serialize::RouteType;
    domain::RouteType type;
    switch (p_route_type) {
    case ProtoRouteType::LINEAR :
        type = domain::RouteType::LINEAR;
        break;
    case ProtoRouteType::CIRCLE :
        type = domain::RouteType::CIRCLE;
        break;
    default :
        type = domain::RouteType::UNKNOWN;
        break;
    }
    return type;
}

} // namespace serialize