aboutsummaryrefslogtreecommitdiff
path: root/libbutl/curl.mxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-09-22 23:32:28 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-09-22 23:32:28 +0200
commitc09cd7512491cee1e82c1ad8128ce9fd4bc3f79b (patch)
treea659ed768d849130ab5780a11b7f791a463a1a91 /libbutl/curl.mxx
parent2a00871f07067f8f9e2de08bb9c8f50e1bf6a650 (diff)
Initial modularization with both Clang and VC hacks
Note: gave up on VC about half way though.
Diffstat (limited to 'libbutl/curl.mxx')
-rw-r--r--libbutl/curl.mxx195
1 files changed, 195 insertions, 0 deletions
diff --git a/libbutl/curl.mxx b/libbutl/curl.mxx
new file mode 100644
index 0000000..57d6e56
--- /dev/null
+++ b/libbutl/curl.mxx
@@ -0,0 +1,195 @@
+// file : libbutl/curl.mxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#ifndef __cpp_modules
+#pragma once
+#endif
+
+// C includes.
+
+#ifndef __cpp_lib_modules
+#include <string>
+#include <type_traits>
+
+#include <cstddef> // size_t
+#include <utility> // forward()
+#include <exception> // invalid_argument
+#endif
+
+// Other includes.
+
+#ifdef __cpp_modules
+export module butl.curl;
+#ifdef __cpp_lib_modules
+import std.core;
+#endif
+import butl.path;
+import butl.process; //@@ MOD TODO: should we re-export?
+import butl.fdstream;
+import butl.small_vector;
+#else
+#include <libbutl/path.mxx>
+#include <libbutl/process.mxx>
+#include <libbutl/fdstream.mxx>
+#include <libbutl/small-vector.mxx>
+#endif
+
+#include <libbutl/export.hxx>
+
+LIBBUTL_MODEXPORT namespace butl
+{
+ // Perform a method (GET, POST, PUT) on a URL using the curl(1) program.
+ // Throw process_error and io_error (both derive from system_error) in case
+ // of errors.
+ //
+ // The I (in) and O (out) can be of the following types/values:
+ //
+ // nullfd Signal that no input/output is expected.
+ //
+ // path Read input/write output from/to a file. If the special "-"
+ // value is used, then instead input is connected to the curl::out
+ // ofdstream member and output -- to the curl::in ifdstream member.
+ // Note that the argument type should be path, not string (i.e.,
+ // pass path("-")).
+ //
+ // other Forwarded as is to process_start(). Normally either int or
+ // auto_fd.
+ //
+ // For example:
+ //
+ // curl (nullfd, // No input expected for GET.
+ // path ("-"), // Write response to curl::in.
+ // 2,
+ // curl::get,
+ // "http://example.org");
+ //
+ // curl (path ("-"), // Read request from curl::out.
+ // path::temp_path (), // Write result to a file.
+ // 2,
+ // curl::post,
+ // "http://example.org");
+ //
+ // curl (nullfd,
+ // fdnull (), // Write result to /dev/null.
+ // 2,
+ // curl::get,
+ // "tftp://localhost/foo");
+ //
+ // Typical usage:
+ //
+ // try
+ // {
+ // curl c (nullfd, // No input expected.
+ // path ("-"), // Output to curl::in.
+ // 2, // Diagnostics to stderr.
+ // curl::get, // GET method.
+ // "https://example.org",
+ // "-A", "foobot/1.2.3"); // Additional curl(1) options.
+ //
+ // for (string s; getline (c.in, s); )
+ // cout << s << endl;
+ //
+ // c.in.close ();
+ //
+ // if (!c.wait ())
+ // ... // curl returned non-zero status.
+ // }
+ // catch (const std::system_error& e)
+ // {
+ // cerr << "curl error: " << e << endl;
+ // }
+ //
+ // Notes:
+ //
+ // 1. If opened, in/out streams are in the binary mode.
+ //
+ // 2. If opened, in/out must be explicitly closed before calling wait().
+ //
+ // 3. Only binary data HTTP POST is currently supported (the --data-binary
+ // curl option).
+ //
+ class LIBBUTL_SYMEXPORT curl: public process
+ {
+ public:
+ enum method_type {get, put, post};
+
+ ifdstream in;
+ ofdstream out;
+
+ template <typename I,
+ typename O,
+ typename E,
+ typename... A>
+ curl (I&& in,
+ O&& out,
+ E&& err,
+ method_type,
+ const std::string& url,
+ A&&... options);
+
+ // Version with the command line callback (see process_run_callback() for
+ // details).
+ //
+ template <typename C,
+ typename I,
+ typename O,
+ typename E,
+ typename... A>
+ curl (const C&,
+ I&& in,
+ O&& out,
+ E&& err,
+ method_type,
+ const std::string& url,
+ A&&... options);
+
+ private:
+ enum method_proto {ftp_get, ftp_put, http_get, http_post};
+ using method_proto_options = small_vector<const char*, 2>;
+
+ method_proto
+ translate (method_type, const std::string& url, method_proto_options&);
+
+ private:
+ template <typename T>
+ struct is_other
+ {
+ using type = typename std::remove_reference<
+ typename std::remove_cv<T>::type>::type;
+
+ static const bool value = !(std::is_same<type, nullfd_t>::value ||
+ std::is_same<type, path>::value);
+ };
+
+ struct io_data
+ {
+ fdpipe pipe;
+ method_proto_options options;
+ std::string storage;
+ };
+
+ int
+ map_in (nullfd_t, method_proto, io_data&);
+
+ int
+ map_in (const path&, method_proto, io_data&);
+
+ template <typename I>
+ typename std::enable_if<is_other<I>::value, I>::type
+ map_in (I&&, method_proto, io_data&);
+
+ int
+ map_out (nullfd_t, method_proto, io_data&);
+
+ int
+ map_out (const path&, method_proto, io_data&);
+
+ template <typename O>
+ typename std::enable_if<is_other<O>::value, O>::type
+ map_out (O&&, method_proto, io_data&);
+ };
+}
+
+#include <libbutl/curl.ixx>
+#include <libbutl/curl.txx>