diff options
Diffstat (limited to 'libbuild2/utility.txx')
-rw-r--r-- | libbuild2/utility.txx | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/libbuild2/utility.txx b/libbuild2/utility.txx new file mode 100644 index 0000000..a91cb15 --- /dev/null +++ b/libbuild2/utility.txx @@ -0,0 +1,115 @@ +// file : libbuild2/utility.txx -*- C++ -*- +// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +namespace build2 +{ + template <typename I, typename F> + void + append_option_values (cstrings& args, const char* o, I b, I e, F&& get) + { + if (b != e) + { + args.reserve (args.size () + (e - b)); + + for (; b != e; ++b) + { + args.push_back (o); + args.push_back (get (*b)); + } + } + } + + template <typename I, typename F> + void + hash_option_values (sha256& cs, const char* o, I b, I e, F&& get) + { + for (; b != e; ++b) + { + cs.append (o); + cs.append (get (*b)); + } + } + + template <typename K> + basic_path<char, K> + relative (const basic_path<char, K>& p) + { + typedef basic_path<char, K> path; + + const dir_path& b (*relative_base); + + if (p.simple () || b.empty ()) + return p; + + if (p.sub (b)) + return p.leaf (b); + + if (p.root_directory () == b.root_directory ()) + { + path r (p.relative (b)); + + if (r.string ().size () < p.string ().size ()) + return r; + } + + return p; + } + + template <typename T, typename F> + T + run (uint16_t verbosity, + const process_env& pe, + const char* args[], + F&& f, + bool err, + bool ignore_exit, + sha256* checksum) + { + process pr (run_start (verbosity, + pe, + args, + 0 /* stdin */, + -1 /* stdout */, + err)); + T r; + string l; // Last line of output. + + try + { + ifdstream is (move (pr.in_ofd), butl::fdstream_mode::skip); + + // Make sure we keep the last line. + // + for (bool last (is.peek () == ifdstream::traits_type::eof ()); + !last && getline (is, l); ) + { + last = (is.peek () == ifdstream::traits_type::eof ()); + + trim (l); + + if (checksum != nullptr) + checksum->append (l); + + if (r.empty ()) + { + r = f (l, last); + + if (!r.empty () && checksum == nullptr) + break; + } + } + + is.close (); + } + catch (const io_error&) + { + // Presumably the child process failed. Let run_finish() deal with that. + } + + if (!(run_finish (args, pr, err, l) || ignore_exit)) + r = T (); + + return r; + } +} |