void ensure_chunks(Chunk *chunks, int *chunk_count, int p, int q, int force) { int count = *chunk_count; for (int i = 0; i < count; i++) { Chunk *chunk = chunks + i; if (chunk_distance(chunk, p, q) >= DELETE_CHUNK_RADIUS) { map_free(&chunk->map); glDeleteBuffers(1, &chunk->position_buffer); glDeleteBuffers(1, &chunk->normal_buffer); glDeleteBuffers(1, &chunk->uv_buffer); Chunk *other = chunks + (--count); memcpy(chunk, other, sizeof(Chunk)); } } int n = CREATE_CHUNK_RADIUS; for (int i = -n; i <= n; i++) { for (int j = -n; j <= n; j++) { int a = p + i; int b = q + j; if (!find_chunk(chunks, count, a, b)) { make_chunk(chunks + count, a, b); count++; if (!force) { *chunk_count = count; return; } } } } *chunk_count = count; }
void ensure_chunks(Chunk *chunks, int *chunk_count, int p, int q, int force) { int count = *chunk_count; for (int i = 0; i < count; i++) { Chunk *chunk = chunks + i; if (chunk_distance(chunk, p, q) >= DELETE_CHUNK_RADIUS) { map_free(&chunk->map); glDeleteBuffers(1, &chunk->position_buffer); glDeleteBuffers(1, &chunk->normal_buffer); glDeleteBuffers(1, &chunk->uv_buffer); Chunk *other = chunks + (--count); memcpy(chunk, other, sizeof(Chunk)); } } int n = force ? 1 : CREATE_CHUNK_RADIUS; for (int i = 0; i <= n; i++) { for (int dp = -n; dp <= n; dp++) { for (int dq = -n; dq <= n; dq++) { int j = MAX(ABS(dp), ABS(dq)); if (i != j) { continue; } int a = p + dp; int b = q + dq; if (!find_chunk(chunks, count, a, b)) { make_chunk(chunks + count, a, b); count++; if (!force) { *chunk_count = count; return; } } } } } *chunk_count = count; }
void fxx() { boost::asio::io_context ioc; auto work = boost::asio::make_work_guard(ioc); std::thread t{[&](){ ioc.run(); }}; boost::asio::ip::tcp::socket sock{ioc}; { //[http_snippet_2 request<empty_body> req; req.version(11); // HTTP/1.1 req.method(verb::get); req.target("/index.htm"); req.set(field::accept, "text/html"); req.set(field::user_agent, "Beast"); //] } { //[http_snippet_3 response<string_body> res; res.version(11); // HTTP/1.1 res.result(status::ok); res.set(field::server, "Beast"); res.body() = "Hello, world!"; res.prepare_payload(); //] } { //[http_snippet_4 flat_buffer buffer; // (The parser is optimized for flat buffers) request<string_body> req; read(sock, buffer, req); //] } { //[http_snippet_5 flat_buffer buffer; response<string_body> res; async_read(sock, buffer, res, [&](error_code ec, std::size_t bytes_transferred) { boost::ignore_unused(bytes_transferred); std::cerr << ec.message() << std::endl; }); //] } { //[http_snippet_6 // This buffer's max size is too small for much of anything flat_buffer buffer{10}; // Try to read a request error_code ec; request<string_body> req; read(sock, buffer, req, ec); if(ec == error::buffer_overflow) std::cerr << "Buffer limit exceeded!" << std::endl; //] } { //[http_snippet_7 response<string_body> res; res.version(11); res.result(status::ok); res.set(field::server, "Beast"); res.body() = "Hello, world!"; res.prepare_payload(); error_code ec; write(sock, res, ec); //] //[http_snippet_8 async_write(sock, res, [&](error_code ec, std::size_t bytes_transferred) { boost::ignore_unused(bytes_transferred); if(ec) std::cerr << ec.message() << std::endl; }); //] } { //[http_snippet_10 response<string_body> res; response_serializer<string_body> sr{res}; //] } { //[http_snippet_18 // Prepare an HTTP/1.1 response with a chunked body response<empty_body> res{status::ok, 11}; res.set(field::server, "Beast"); // Set Transfer-Encoding to "chunked". // If a Content-Length was present, it is removed. res.chunked(true); // Set up the serializer response_serializer<empty_body> sr{res}; // Write the header first write_header(sock, sr); // Now manually emit three chunks: boost::asio::write(sock, make_chunk(get_next_chunk_body())); boost::asio::write(sock, make_chunk(get_next_chunk_body())); boost::asio::write(sock, make_chunk(get_next_chunk_body())); // We are responsible for sending the last chunk: boost::asio::write(sock, make_chunk_last()); //] } { //[http_snippet_19 // Prepare a set of chunk extension to emit with the body chunk_extensions ext; ext.insert("mp3"); ext.insert("title", "Beale Street Blues"); ext.insert("artist", "W.C. Handy"); // Write the next chunk with the chunk extensions // The implementation will make a copy of the extensions object, // so the caller does not need to manage lifetime issues. boost::asio::write(sock, make_chunk(get_next_chunk_body(), ext)); // Write the next chunk with the chunk extensions // The implementation will make a copy of the extensions object, storing the copy // using the custom allocator, so the caller does not need to manage lifetime issues. boost::asio::write(sock, make_chunk(get_next_chunk_body(), ext, std::allocator<char>{})); // Write the next chunk with the chunk extensions // The implementation allocates memory using the default allocator and takes ownership // of the extensions object, so the caller does not need to manage lifetime issues. // Note: ext is moved boost::asio::write(sock, make_chunk(get_next_chunk_body(), std::move(ext))); //] } { //[http_snippet_20 // Manually specify the chunk extensions. // Some of the strings contain spaces and a period and must be quoted boost::asio::write(sock, make_chunk(get_next_chunk_body(), ";mp3" ";title=\"Danny Boy\"" ";artist=\"Fred E. Weatherly\"" )); //] } { //[http_snippet_21 // Prepare a chunked HTTP/1.1 response with some trailer fields response<empty_body> res{status::ok, 11}; res.set(field::server, "Beast"); // Inform the client of the trailer fields we will send res.set(field::trailer, "Content-MD5, Expires"); res.chunked(true); // Serialize the header and two chunks response_serializer<empty_body> sr{res}; write_header(sock, sr); boost::asio::write(sock, make_chunk(get_next_chunk_body())); boost::asio::write(sock, make_chunk(get_next_chunk_body())); // Prepare the trailer fields trailer; trailer.set(field::content_md5, "f4a5c16584f03d90"); trailer.set(field::expires, "never"); // Emit the trailer in the last chunk. // The implementation will use the default allocator to create the storage for holding // the serialized fields. boost::asio::write(sock, make_chunk_last(trailer)); //] } { //[http_snippet_22 // Use a custom allocator for serializing the last chunk fields trailer; trailer.set(field::approved, "yes"); boost::asio::write(sock, make_chunk_last(trailer, std::allocator<char>{})); //] } { //[http_snippet_23 // Manually emit a trailer. // We are responsible for ensuring that the trailer format adheres to the specification. string_view ext = "Content-MD5: f4a5c16584f03d90\r\n" "Expires: never\r\n" "\r\n"; boost::asio::write(sock, make_chunk_last(boost::asio::const_buffer{ext.data(), ext.size()})); //] } { //[http_snippet_24 // Prepare a chunked HTTP/1.1 response and send the header response<empty_body> res{status::ok, 11}; res.set(field::server, "Beast"); res.chunked(true); response_serializer<empty_body> sr{res}; write_header(sock, sr); // Obtain three body buffers up front auto const cb1 = get_next_chunk_body(); auto const cb2 = get_next_chunk_body(); auto const cb3 = get_next_chunk_body(); // Manually emit a chunk by first writing the chunk-size header with the correct size boost::asio::write(sock, chunk_header{ boost::asio::buffer_size(cb1) + boost::asio::buffer_size(cb2) + boost::asio::buffer_size(cb3)}); // And then output the chunk body in three pieces ("chunk the chunk") boost::asio::write(sock, cb1); boost::asio::write(sock, cb2); boost::asio::write(sock, cb3); // When we go this deep, we are also responsible for the terminating CRLF boost::asio::write(sock, chunk_crlf{}); //] } } // fxx()