protohackers

My solutions to the protohackers.com challenges.
git clone git://henryandlizzy.uk/protohackers
Log | Files | Refs

protohack-0.cpp (1404B)


      1 #include "inet.hpp"
      2 
      3 #include <poll.h>
      4 
      5 #include <algorithm>
      6 #include <iostream>
      7 #include <map>
      8 
      9 int poll(std::span<struct pollfd> pfds, int timeout = INFTIM)
     10 {
     11 	if (int n = ::poll(pfds.data(), pfds.size(), timeout); n != -1)
     12 		return n;
     13 	err(1, "poll");
     14 }
     15 
     16 int main()
     17 {
     18 	std::map<int, descriptor> clients;
     19 	auto incoming_socket = inet::listen(SOCK_STREAM);
     20 	std::cout << "Protohack 0: Smoke Test\n";
     21 
     22 	for (;;)
     23 	{
     24 		size_t const pollen = clients.size() + 1;
     25 		pollfd events_buf[pollen];
     26 		std::span events{events_buf, pollen};
     27 
     28 		auto& socket_event = events.front();
     29 		auto client_events = events.subspan(1);
     30 
     31 		socket_event = pollfd{incoming_socket, POLLIN, 0};
     32 
     33 		std::transform(clients.cbegin(), clients.cend(), client_events.begin(), [](auto& c) {
     34 			return pollfd{c.second, POLLIN, 0};
     35 		});
     36 
     37 		int ready = poll(events);
     38 
     39 		if (socket_event.revents & POLLIN)
     40 		{
     41 			auto conn = inet::accept(incoming_socket);
     42 			clients[conn] = std::move(conn);
     43 			if (not --ready)
     44 				continue;
     45 		}
     46 
     47 		for (auto& ev : client_events)
     48 		{
     49 			if (~ev.revents & POLLIN)
     50 				continue;
     51 
     52 			char data_buf[0x1000];
     53 			auto data = read(ev.fd, std::span{data_buf});
     54 
     55 			if (data.empty())
     56 			{
     57 				std::cout << "* " << ev.fd << " disconnected\n";
     58 				clients.erase(ev.fd);
     59 				continue;
     60 			}
     61 
     62 			std::cout << "* " << ev.fd << ": " << data.size() << " bytes\n";
     63 			write(ev.fd, data);
     64 
     65 			if (not --ready)
     66 				break;
     67 		}
     68 	}
     69 }