1 /* ===========================================================================
2  *
3  *                            PUBLIC DOMAIN NOTICE
4  *               National Center for Biotechnology Information
5  *
6  *  This software/database is a "United States Government Work" under the
7  *  terms of the United States Copyright Act.  It was written as part of
8  *  the author's official duties as a United States Government employee and
9  *  thus cannot be copyrighted.  This software/database is freely available
10  *  to the public for use. The National Library of Medicine and the U.S.
11  *  Government have not placed any restriction on its use or reproduction.
12  *
13  *  Although all reasonable efforts have been taken to ensure the accuracy
14  *  and reliability of the software and data, the NLM and the U.S.
15  *  Government do not and cannot warrant the performance or results that
16  *  may be obtained by using this software or data. The NLM and the U.S.
17  *  Government disclaim all warranties, express or implied, including
18  *  warranties of performance, merchantability or fitness for any particular
19  *  purpose.
20  *
21  *  Please cite the author in any work or product based on this material.
22  *
23  * ===========================================================================
24  *
25  * Project:
26  *  sratools command line tool
27  *
28  * Purpose:
29  *  Declare and define compile-time constants (and some functions on them)
30  *
31  */
32 
33 #pragma once
34 
35 #include <klib/strings.h> /* SDL_CGI */
36 
37 #include <cassert>
38 #include <algorithm>
39 #include <cstring>
40 #include <cstdlib>
41 
42 #include "env_vars.h"
43 #include "util.hpp"
44 
45 namespace constants {
46 
47 /// @brief constants used for tool names
48 struct tool_name {
49     /// @brief tools names as symbols
50     enum {
51         FASTERQ_DUMP,
52         FASTQ_DUMP,
53         PREFETCH,
54         SAM_DUMP,
55         SRA_PILEUP,
56         SRAPATH,
57         END_ENUM
58     };
59 
60     /// @brief array of tool names in same order as above enum
realconstants::tool_name61     static char const *const *real() {
62         static char const *const value[] = {
63             "fasterq-dump-orig",
64             "fastq-dump-orig",
65             "prefetch-orig",
66             "sam-dump-orig",
67             "sra-pileup-orig",
68             "srapath-orig"
69         };
70         return value;
71     }
72 
73     /// @brief array of impersonated tool names in same order as above enum
runasNamesconstants::tool_name74     static char const *const *runasNames() {
75         static char const *const value[] = {
76             "fasterq-dump",
77             "fastq-dump",
78             "prefetch",
79             "sam-dump",
80             "sra-pileup",
81             "srapath"
82         };
83         return value;
84     }
85 
86     /// @brief get full path to tool by id
pathconstants::tool_name87     static char const *path(int const iid)
88     {
89         extern std::vector<opt_string> load_tool_paths(int n, char const *const *runas, char const *const *real);
90         extern void pathHelp [[noreturn]] (std::string const &toolname);
91 
92         static auto const cache = load_tool_paths(END_ENUM, runasNames(), real());
93         auto const &result = cache.at(iid);
94         if (result)
95             return result.value().c_str();
96 
97         pathHelp(runas(iid));
98     }
99 
100     /// @brief convert id to string
101     ///
102     /// @param iid integer id of tool (range checked)
103     ///
104     /// @returns the real name of the tool in the filesystem
realconstants::tool_name105     static char const *real(int const iid) {
106         assert(0 <= iid && iid < END_ENUM);
107         if (0 <= iid && iid < END_ENUM)
108             return real()[iid];
109         throw std::range_error("unknown tool id");
110     }
111 
112     /// @brief convert id to string
113     ///
114     /// @param iid integer id of tool (range checked)
115     ///
116     /// @returns the impersonated name of the tool
runasconstants::tool_name117     static char const *runas(int const iid) {
118         assert(0 <= iid && iid < END_ENUM);
119         if (0 <= iid && iid < END_ENUM)
120             return runasNames()[iid];
121         throw std::range_error("unknown tool id");
122     }
123 
124     /// @brief convert impersonated name to id
125     ///
126     /// @param qry the impersonated name
127     ///
128     /// @returns the id or -1 if not found
lookup_iidconstants::tool_name129     static int lookup_iid(char const *const qry) {
130         auto const values = runasNames();
131         int f = 0;
132         int e = END_ENUM;
133 
134         while (f < e) {
135             auto const m = f + ((e - f) >> 1);
136             auto const c = strcmp(values[m], qry);
137             if (c < 0)
138                 f = m + 1;
139             else if (c > 0)
140                 e = m;
141             else
142                 return m;
143         }
144         return -1;
145     }
146 };
147 
148 /// @brief constants used for calling SRA Data Locator
149 struct resolver {
versionconstants::resolver150     static constexpr char const *version() { return "130"; }
151 #ifdef SDL_CGI
urlconstants::resolver152     static constexpr char const *url() { return SDL_CGI; }
153 #else
urlconstants::resolver154     static constexpr char const *url() { return "https://trace.ncbi.nlm.nih.gov/Traces/sdl/2/retrieve"; }
155 #endif
156 
157     /// @brief the current unstable version of SDL response JSON
158     ///
159     /// @Note THIS NEEDS TO TRACK ACTUAL SDL VALUE
unstable_versionconstants::resolver160     static constexpr char const *unstable_version() {
161         return "2";
162     }
163 };
164 
165 /// @brief environment variables for passing information to the driven tool
166 struct env_var {
167     /// @brief environment variables as symbolic names
168     enum {
169         CACHE_NEED_CE,
170         CACHE_NEED_PMT,
171         CACHE_URL,
172         CACHE_VDBCACHE,
173         CE_TOKEN,
174         LOCAL_URL,
175         LOCAL_VDBCACHE,
176         REMOTE_NEED_CE,
177         REMOTE_NEED_PMT,
178         REMOTE_URL,
179         REMOTE_VDBCACHE,
180         SIZE_URL,
181         SIZE_VDBCACHE,
182         END_ENUM
183     };
184 
185     /// @brief array of environment variables in the same order as the enum above.
namesconstants::env_var186     static char const *const *names() {
187         static char const *const value[] = {
188             ENV_VAR_CACHE_NEED_CE,
189             ENV_VAR_CACHE_NEED_PMT,
190             ENV_VAR_CACHE_URL,
191             ENV_VAR_CACHE_VDBCACHE,
192             ENV_VAR_CE_TOKEN,
193             ENV_VAR_LOCAL_URL,
194             ENV_VAR_LOCAL_VDBCACHE,
195             ENV_VAR_REMOTE_NEED_CE,
196             ENV_VAR_REMOTE_NEED_PMT,
197             ENV_VAR_REMOTE_URL,
198             ENV_VAR_REMOTE_VDBCACHE,
199             ENV_VAR_SIZE_URL,
200             ENV_VAR_SIZE_VDBCACHE
201         };
202         return value;
203     }
204 
205     /// @brief convert id to string
206     ///
207     /// @param iid integer id of env-var (range checked)
208     ///
209     /// @returns the env-var name as a string
nameconstants::env_var210     static char const *name(int const iid) {
211         assert(0 <= iid && iid < END_ENUM);
212         if (0 <= iid && iid < END_ENUM)
213             return names()[iid];
214         throw std::range_error("unknown environment variable id");
215     }
216 
217     /// @brief convert string to id
218     ///
219     /// @param qry the env-var name
220     ///
221     /// @returns the id or -1 if not found
findconstants::env_var222     static int find(char const *qry) {
223         auto const values = names();
224         int f = 0;
225         int e = END_ENUM;
226 
227         while (f < e) {
228             auto const m = f + ((e - f) >> 1);
229             auto const c = strcmp(values[m], qry);
230             if (c < 0)
231                 f = m + 1;
232             else if (c > 0)
233                 e = m;
234             else
235                 return m;
236         }
237         return -1;
238     }
239 
240     /// @brief unset environment variable by symbolic id
241     ///
242     /// @param iid the variable to unset
unsetconstants::env_var243     static void unset(int const iid) {
244 #if WINDOWS
245         std::string n = name(iid);
246         n += "=";
247         _putenv(n.c_str());
248 #else
249         unsetenv(name(iid));
250 #endif
251     }
252 
253     /// @brief set (or unset) environment variable by symbolic id
254     ///
255     /// @param iid the variable to set
256     /// @param value the new value, unset if null
257     /// @param overwrite overwrite the value if it is already there, default is to overwrite
setconstants::env_var258     static void set(int const iid, char const *value, bool overwrite = true) {
259         auto const envar = name(iid);
260         EnvironmentVariables::set(envar, value ? EnvironmentVariables::Value(value) : EnvironmentVariables::Value());
261     }
262 };
263 
264 }
265