// file : libbuild2/utility.ixx -*- C++ -*- // license : MIT; see accompanying LICENSE file #include // strlen() strchr() namespace build2 { inline bool run_wait (const cstrings& args, process& pr, const location& loc) { return run_wait (args.data (), pr, loc); } // Note: these functions are also used in the run() implementations. // LIBBUILD2_SYMEXPORT bool run_finish_impl (const char* const*, process&, bool fail, const string&, uint16_t, bool = false, const location& = {}); LIBBUILD2_SYMEXPORT bool run_finish_impl (diag_buffer&, const char* const*, process&, bool fail, uint16_t, bool = false, const location& = {}); inline void run_finish (const char* const* args, process& pr, uint16_t v, bool on, const location& loc) { run_finish_impl (args, pr, true /* fail */, string (), v, on, loc); } inline void run_finish (const cstrings& args, process& pr, uint16_t v, bool on, const location& loc) { run_finish (args.data (), pr, v, on, loc); } inline void run_finish (const char* const* args, process& pr, const string& l, uint16_t v, bool on, const location& loc) { run_finish_impl (args, pr, true, l, v, on, loc); } inline bool run_finish_code (const char* const* args, process& pr, uint16_t v, bool on, const location& loc) { return run_finish_impl (args, pr, false, string (), v, on, loc); } inline bool run_finish_code (const cstrings& args, process& pr, uint16_t v, bool on, const location& loc) { return run_finish_code (args.data (), pr, v, on, loc); } inline bool run_finish_code (const char* const* args, process& pr, const string& l, uint16_t v, bool on, const location& loc) { return run_finish_impl (args, pr, false, l, v, on, loc); } inline void run_finish (diag_buffer& dbuf, const char* const* args, process& pr, uint16_t v, bool on, const location& loc) { run_finish_impl (dbuf, args, pr, true /* fail */, v, on, loc); } inline void run_finish (diag_buffer& dbuf, const cstrings& args, process& pr, uint16_t v, bool on, const location& loc) { run_finish_impl (dbuf, args.data (), pr, true, v, on, loc); } inline bool run_finish_code (diag_buffer& dbuf, const char* const* args, process& pr, uint16_t v, bool on, const location& loc) { return run_finish_impl (dbuf, args, pr, false, v, on, loc); } inline bool run_finish_code (diag_buffer& dbuf, const cstrings& args, process& pr, uint16_t v, bool on, const location& loc) { return run_finish_impl (dbuf, args.data (), pr, false, v, on, loc); } template inline T run (context& ctx, uint16_t verbosity, const process_env& pe, const char* const* args, F&& f, bool err, bool ignore_exit, sha256* checksum) { T r; if (!run (ctx, verbosity, pe, args, verbosity - 1, [&r, &f] (string& l, bool last) // Small function optimmization. { r = f (l, last); return r.empty (); }, true /* trim */, err, ignore_exit, checksum)) r = T (); return r; } template inline T run (context& ctx, const process_env& pe, const char* const* args, uint16_t finish_verbosity, F&& f, bool err, bool ignore_exit, sha256* checksum) { T r; if (!run (ctx, verb_never, pe, args, finish_verbosity, [&r, &f] (string& l, bool last) { r = f (l, last); return r.empty (); }, true /* trim */, err, ignore_exit, checksum)) r = T (); return r; } inline void hash_path (sha256& cs, const path& p, const dir_path& prefix) { // Note: for efficiency we don't use path::leaf() and "skip" the prefix // without copying. // const char* s (p.string ().c_str ()); if (!prefix.empty () && p.sub (prefix)) { s += prefix.size (); // Does not include trailing slash except for root. if (path::traits_type::is_separator (*s)) ++s; } cs.append (s); } template inline void append_options (cstrings& args, T& s, const variable& var, const char* e) { append_options (args, s[var], e); } template inline void append_options (strings& args, T& s, const variable& var, const char* e) { append_options (args, s[var], e); } template inline void append_options (sha256& csum, T& s, const variable& var) { append_options (csum, s[var]); } template inline void append_options (cstrings& args, T& s, const char* var, const char* e) { append_options (args, s[var], e); } template inline void append_options (strings& args, T& s, const char* var, const char* e) { append_options (args, s[var], e); } template inline void append_options (sha256& csum, T& s, const char* var) { append_options (csum, s[var]); } inline void append_options (cstrings& args, const strings& sv, const char* e) { if (size_t n = sv.size ()) append_options (args, sv, n, e); } inline void append_options (strings& args, const strings& sv, const char* e) { if (size_t n = sv.size ()) append_options (args, sv, n, e); } inline void append_options (sha256& csum, const strings& sv) { if (size_t n = sv.size ()) append_options (csum, sv, n); } template inline bool find_option (const char* o, T& s, const variable& var, bool ic) { return find_option (o, s[var], ic); } template inline bool find_option (const char* o, T& s, const char* var, bool ic) { return find_option (o, s[var], ic); } inline bool compare_option (const char* o, const char* s, bool ic) { return s != nullptr && (ic ? icasecmp (s, o) : strcmp (s, o)) == 0; } inline bool compare_option (const char* o, const string& s, bool ic) { return ic ? icasecmp (s, o) == 0 : s == o; } template inline I find_option (const char* o, I b, I e, bool ic) { for (; b != e; ++b) if (compare_option (o, *b, ic)) return b; return e; } template inline bool find_options (const initializer_list& os, T& s, const variable& var, bool ic) { return find_options (os, s[var], ic); } template inline bool find_options (const initializer_list& os, T& s, const char* var, bool ic) { return find_options (os, s[var], ic); } template inline const string* find_option_prefix (const char* p, T& s, const variable& var, bool ic) { return find_option_prefix (p, s[var], ic); } template inline const string* find_option_prefix (const char* p, T& s, const char* var, bool ic) { return find_option_prefix (p, s[var], ic); } inline bool compare_option_prefix (const char* p, size_t n, const char* s, bool ic) { return s != nullptr && (ic ? icasecmp (s, p, n) : strncmp (s, p, n)) == 0; } inline bool compare_option_prefix (const char* p, size_t n, const string& s, bool ic) { return (ic ? icasecmp (s, p, n) : s.compare (0, n, p)) == 0; } template inline I find_option_prefix (const char* p, I b, I e, bool ic) { size_t n (strlen (p)); for (; b != e; ++b) if (compare_option_prefix (p, n, *b, ic)) return b; return e; } template inline const string* find_option_prefixes (const initializer_list& ps, T& s, const variable& var, bool ic) { return find_option_prefixes (ps, s[var], ic); } template inline const string* find_option_prefixes (const initializer_list& ps, T& s, const char* var, bool ic) { return find_option_prefixes (ps, s[var], ic); } // hash_environment() // inline void hash_environment (sha256& cs, const char* n) { cs.append (n); if (optional v = getenv (n)) cs.append (*v); } inline void hash_environment (sha256& cs, const string& n) { hash_environment (cs, n.c_str ()); } inline void hash_environment (sha256& cs, initializer_list ns) { for (const char* n: ns) hash_environment (cs, n); } inline string hash_environment (initializer_list ns) { sha256 cs; hash_environment (cs, ns); return cs.string (); } inline void hash_environment (sha256& cs, const cstrings& ns) { for (const char* n: ns) hash_environment (cs, n); } inline string hash_environment (const cstrings& ns) { sha256 cs; hash_environment (cs, ns); return cs.string (); } inline void hash_environment (sha256& cs, const strings& ns) { for (const string& n: ns) hash_environment (cs, n); } inline string hash_environment (const strings& ns) { sha256 cs; hash_environment (cs, ns); return cs.string (); } inline void hash_environment (sha256& cs, const char* const* ns) { if (ns != nullptr) { for (; *ns != nullptr; ++ns) hash_environment (cs, *ns); } } inline string hash_environment (const char* const* ns) { sha256 cs; hash_environment (cs, ns); return cs.string (); } // find_stem() // inline size_t find_stem (const string& s, size_t s_p, size_t s_n, const char* stem, const char* seps) { auto sep = [seps] (char c) -> bool { return strchr (seps, c) != nullptr; }; size_t m (strlen (stem)); size_t p (s.find (stem, s_p, m)); return (p != string::npos && ( p == s_p || sep (s[p - 1])) && // Separated beginning. ((p + m) == s_n || sep (s[p + m]))) // Separated end. ? p : string::npos; } }