1 #ifndef _STRINGS_H
2 #define _STRINGS_H
3
4 #include "../../lib/compat.h"
5 #include "cxx_macros.h"
6 #include <string>
7 #include <vector>
8
9 // Various symbols that we will need.
10 // For Greek letters, see greek.h
11
12 #define DEGREE_LATIN1 "\xB0"
13 #define DEGREE_UTF8 "\xC2\xB0"
14 #define COPYRIGHT_UTF8 "\xC2\xA9"
15 #define WHITESPACE " \f\n\r\t\v"
16 #define DIGITS "0123456789"
17
18 // A class adding a few utilities to a vector of strings
19
20 class StringList : public std::vector<std::string> {
21 private:
22 mutable char ** c_strings;
23 mutable size_t c_strings_size;
24 void delstrings() const;
25
26 public:
27 typedef std::vector<std::string>::iterator iterator;
28 typedef std::vector<std::string>::const_iterator const_iterator;
29
30 StringList();
31 StringList(const StringList &s);
32 StringList(size_t n, const std::string &s);
33 StringList(const std::string &s, char tokenizer = ' ');
34 ~StringList();
35 StringList & operator = (const StringList &s);
36 std::string & operator[] (size_t n);
37 const std::string & operator[] (size_t n) const;
38
39 void push_back(const char *);
40 void push_back(const std::string &);
41 void push_back(const StringList &);
42 void stripspace();
43 void eraseempty();
44 void toupper();
45 void tolower();
46 void utf8ize();
47 std::string flatten(char spacer = ' ') const;
48 char ** c_str() const;
49 };
50
51 // Enum of distance units
52 enum distance_unit { DIST_LY, DIST_PC, DIST_KPC,
53 DIST_AU, DIST_KM, DIST_MI, N_DIST };
54
55 extern double distance_conversion[N_DIST];
56 extern const char * distance_name[N_DIST];
57 extern const char * distance_cname[N_DIST];
58
59 // Useful string functions
60
61 namespace starstrings {
62
63 // Old compilers (egcs-2.91.66, for example) define tolower, toupper as
64 // macros, which messes everything up. So fix this:
65 int toupper(int);
66 int tolower(int);
67
68 // convert numbers to strings
69 std::string ltoa(long int l, int width = 0, bool zeropadding = false);
70 std::string itoa(int i, int width = 0, bool zeropadding = false);
71 std::string ftoa(double d, int precision = 4, int integer_width = 0,
72 bool zeropadding = false);
73
74 // Function behaving like sprintf() for use with gettext
75 std::string ssprintf(const char * format, ...);
76
77 // string utilities
78 bool isempty(const std::string &);
79 std::string uppercase(const std::string &);
80 std::string lowercase(const std::string &);
81 void stripspace(std::string &);
82 void toupper(std::string &);
83 void tolower(std::string &);
84 void utf8ize(std::string &);
85 void addgreek(std::string &);
86 bool find_and_replace(std::string & haystack, const std::string & needle,
87 const std::string & replacement, unsigned posn = 0);
88
89 // compare strings
90 bool compare(const std::string &, const std::string &);
91 bool case_compare(const std::string &, const std::string &);
92 bool compare_n(const std::string &, const std::string &, size_t length);
93 bool case_compare_n(const std::string &, const std::string &, size_t length);
94
95 // Optimization: do case-insensitive comparison assuming that first
96 // argument is already converted to uppercase:
97 bool case_compare1(const std::string &, const std::string &);
98 bool case_compare1_n(const std::string &, const std::string &, size_t len);
99
100 // Functions to convert between string and radian representations of
101 // coordinates. "symbols" decides whether or not to append h,m,s,deg,',"
102 StringList dec_to_strs(double declination, bool symbols = false);
103 StringList ra_to_strs(double right_ascension, bool celestial = true,
104 bool symbols = false);
105 std::string dec_to_str(double declination, char spacer = ' ',
106 bool symbols = false);
107 std::string ra_to_str(double right_ascension, char spacer = ' ',
108 bool celestial_coords = true, bool symbols = false);
109
110 double strs_to_dec(const StringList &decstrings);
111 double strs_to_ra(const StringList &rastrings, bool celestial_coords = true);
112 double strs_to_dec(const std::string &d, const std::string &m,
113 const std::string &s);
114 double strs_to_ra(const std::string &h, const std::string &m,
115 const std::string &s, bool celestial_coords = true);
116 double str_to_dec(const std::string &decstring, char tokenizer = ' ');
117 double str_to_ra(const std::string &rastring, char tokenizer = ' ',
118 bool celestial_coords = true);
119
120 distance_unit str_to_unit(const std::string &);
121 std::string distance_to_str(double distance_ly, distance_unit unit);
122 std::string distance_to_str(double distance_ly, const distance_unit *arr = 0);
123
124 } // end of namespace
125
126
127 // inline function definitions
128
129 inline void
delstrings()130 StringList::delstrings() const
131 {
132 for (size_t i = 0; i < c_strings_size; i++) delete [] c_strings[i];
133 delete [] c_strings; c_strings = 0;
134 }
135
StringList()136 inline StringList::StringList() :
137 std::vector<std::string>(), c_strings(0), c_strings_size(0) { }
138
StringList(const StringList & s)139 inline StringList::StringList(const StringList &s) :
140 std::vector<std::string>(dynamic_cast<const std::vector<std::string> &>(s)),
141 c_strings(0), c_strings_size(0) { }
142
StringList(size_t n,const std::string & s)143 inline StringList::StringList(size_t n, const std::string &s) :
144 std::vector<std::string>(n, s), c_strings(0), c_strings_size(0) { }
145
~StringList()146 inline StringList::~StringList() { delstrings(); }
147
148 inline StringList &
149 StringList::operator = (const StringList &s)
150 {
151 if (this == &s) return *this;
152 std::vector<std::string>::operator =
153 (dynamic_cast<const std::vector<std::string> &>(s));
154 delstrings();
155 return *this;
156 }
157
158 inline std::string &
159 StringList::operator [] (size_t n)
160 {
161 if (n >= size()) resize(n + 1, "");
162 return std::vector<std::string>::operator[] (n);
163 }
164
165 inline const std::string &
166 StringList::operator [] (size_t n) const
167 {
168 static std::string empty_str("");
169 if (n < size()) return std::vector<std::string>::operator[] (n);
170 else return empty_str;
171 }
172
173 inline void
push_back(const char * s)174 StringList::push_back(const char *s)
175 { std::vector<std::string>::push_back(std::string(s)); }
176
177 inline void
push_back(const std::string & s)178 StringList::push_back(const std::string &s)
179 { std::vector<std::string>::push_back(s); }
180
181 inline void
push_back(const StringList & s)182 StringList::push_back(const StringList &s)
183 { citerate (StringList, s, i) push_back(*i); }
184
185 inline void
stripspace()186 StringList::stripspace()
187 { iterate (StringList, *this, i) starstrings::stripspace(*i); }
188
189 inline void
eraseempty()190 StringList::eraseempty()
191 {
192 stripspace();
193 iterate (StringList, *this, i)
194 if (starstrings::isempty(*i))
195 erase(i--);
196 }
197
198 inline void
toupper()199 StringList::toupper()
200 { iterate (StringList, *this, i) starstrings::toupper(*i); }
201
202 inline void
tolower()203 StringList::tolower()
204 { iterate (StringList, *this, i) starstrings::tolower(*i); }
205
206 inline void
utf8ize()207 StringList::utf8ize()
208 { iterate (StringList, *this, i) starstrings::utf8ize(*i); }
209
210 inline int
tolower(int c)211 starstrings::tolower(int c)
212 { return (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c; }
213
214 inline int
toupper(int c)215 starstrings::toupper(int c)
216 { return (c >= 'a' && c <= 'z') ? (c + 'A' - 'a') : c; }
217
218 inline std::string
itoa(int i,int width,bool zeropadding)219 starstrings::itoa(int i, int width, bool zeropadding)
220 { return starstrings::ltoa(static_cast<long int>(i), width, zeropadding); }
221
222 inline bool
isempty(const std::string & s)223 starstrings::isempty(const std::string &s)
224 { return s.find_first_not_of(WHITESPACE) >= s.size(); }
225
226 inline void
stripspace(std::string & s)227 starstrings::stripspace(std::string &s)
228 {
229 s.replace(0, s.find_first_not_of(WHITESPACE), "");
230 s.replace(s.find_last_not_of(WHITESPACE) + 1, s.size(), "");
231 }
232
233 inline bool
find_and_replace(std::string & haystack,const std::string & needle,const std::string & replacement,unsigned start_posn)234 starstrings::find_and_replace(std::string & haystack,
235 const std::string & needle,
236 const std::string & replacement,
237 unsigned start_posn)
238 {
239 if (start_posn >= haystack.size()) return false;
240
241 size_t posn = haystack.find(needle, start_posn);
242 if (posn < haystack.size()) {
243 haystack.replace(posn, needle.size(), replacement);
244 return true;
245 }
246 else return false;
247 }
248
249 inline std::string
uppercase(const std::string & s)250 starstrings::uppercase(const std::string &s)
251 {
252 std::string result = s;
253 iterate (std::string, result, i) *i = starstrings::toupper(*i);
254 return result;
255 }
256
257 inline std::string
lowercase(const std::string & s)258 starstrings::lowercase(const std::string &s)
259 {
260 std::string result = s;
261 iterate (std::string, result, i) *i = starstrings::tolower(*i);
262 return result;
263 }
264
265 inline void
toupper(std::string & s)266 starstrings::toupper(std::string &s)
267 { iterate (std::string, s, i) *i = starstrings::toupper(*i); }
268
269 inline void
tolower(std::string & s)270 starstrings::tolower(std::string &s)
271 { iterate (std::string, s, i) *i = starstrings::tolower(*i); }
272
273 inline bool
compare(const std::string & s1,const std::string & s2)274 starstrings::compare(const std::string &s1, const std::string &s2)
275 { return s1 == s2; }
276
277 inline bool
case_compare(const std::string & s1,const std::string & s2)278 starstrings::case_compare(const std::string &s1, const std::string &s2)
279 { return uppercase(s1) == uppercase(s2); }
280
281 inline bool
case_compare1(const std::string & s1,const std::string & s2)282 starstrings::case_compare1(const std::string &s1, const std::string &s2)
283 { return s1 == uppercase(s2); }
284
285 inline bool
compare_n(const std::string & s1,const std::string & s2,size_t n)286 starstrings::compare_n(const std::string &s1, const std::string &s2,
287 size_t n)
288 { return std::string(s1, 0, n) == std::string(s2, 0, n); }
289
290 inline bool
case_compare_n(const std::string & s1,const std::string & s2,size_t n)291 starstrings::case_compare_n(const std::string &s1, const std::string &s2,
292 size_t n)
293 { return compare_n(uppercase(s1), uppercase(s2), n); }
294
295 inline bool
case_compare1_n(const std::string & s1,const std::string & s2,size_t n)296 starstrings::case_compare1_n(const std::string &s1, const std::string &s2,
297 size_t n)
298 { return compare_n(s1, uppercase(s2), n); }
299
300 inline std::string
dec_to_str(double declination,char spacer,bool symbols)301 starstrings::dec_to_str(double declination, char spacer, bool symbols)
302 { return dec_to_strs(declination, symbols).flatten(spacer); }
303
304 inline std::string
ra_to_str(double right_ascension,char spacer,bool celestial_coords,bool symbols)305 starstrings::ra_to_str(double right_ascension, char spacer,
306 bool celestial_coords, bool symbols)
307 { return ra_to_strs(right_ascension,celestial_coords,symbols).flatten(spacer); }
308
309 inline double
str_to_dec(const std::string & decstring,char tokenizer)310 starstrings::str_to_dec(const std::string &decstring, char tokenizer)
311 { return strs_to_dec(StringList(decstring, tokenizer)); }
312
313 inline double
str_to_ra(const std::string & rastring,char tokenizer,bool celestial_coords)314 starstrings::str_to_ra(const std::string &rastring, char tokenizer,
315 bool celestial_coords)
316 { return strs_to_ra(StringList(rastring, tokenizer), celestial_coords); }
317
318 #endif
319
320