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