File: | src/fits/GFitsHeaderCard.cpp |
Location: | line 862, column 13 |
Description: | Attempt to free released memory |
1 | /*************************************************************************** | |||
2 | * GFitsHeaderCard.cpp - FITS header card class * | |||
3 | * ----------------------------------------------------------------------- * | |||
4 | * copyright (C) 2008-2013 by Juergen Knoedlseder * | |||
5 | * ----------------------------------------------------------------------- * | |||
6 | * * | |||
7 | * This program is free software: you can redistribute it and/or modify * | |||
8 | * it under the terms of the GNU General Public License as published by * | |||
9 | * the Free Software Foundation, either version 3 of the License, or * | |||
10 | * (at your option) any later version. * | |||
11 | * * | |||
12 | * This program is distributed in the hope that it will be useful, * | |||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
15 | * GNU General Public License for more details. * | |||
16 | * * | |||
17 | * You should have received a copy of the GNU General Public License * | |||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. * | |||
19 | * * | |||
20 | ***************************************************************************/ | |||
21 | /** | |||
22 | * @file GFitsHeaderCard.cpp | |||
23 | * @brief FITS header card class implementation | |||
24 | * @author Juergen Knoedlseder | |||
25 | */ | |||
26 | ||||
27 | /* __ Includes ___________________________________________________________ */ | |||
28 | #ifdef HAVE_CONFIG_H1 | |||
29 | #include <config.h> | |||
30 | #endif | |||
31 | #include <cfloat> | |||
32 | #include <climits> | |||
33 | #include "GException.hpp" | |||
34 | #include "GTools.hpp" | |||
35 | #include "GFitsCfitsio.hpp" | |||
36 | #include "GFits.hpp" | |||
37 | #include "GFitsHeaderCard.hpp" | |||
38 | ||||
39 | /* __ Method name definitions ____________________________________________ */ | |||
40 | #define G_COPY_DTYPE"GFitsHeaderCard::copy_dtype(GFitsHeaderCard&)" "GFitsHeaderCard::copy_dtype(GFitsHeaderCard&)" | |||
41 | #define G_FREE_DTYPE"GFitsHeaderCard::free_dtype()" "GFitsHeaderCard::free_dtype()" | |||
42 | #define G_SET_DTYPE"GFitsHeaderCard::set_dtype(std::string&)" "GFitsHeaderCard::set_dtype(std::string&)" | |||
43 | #define G_READ_NUM"GFitsHeaderCard::read(void*, int&)" "GFitsHeaderCard::read(void*, int&)" | |||
44 | #define G_READ_STR"GFitsHeaderCard::read(void*, std::string&)" "GFitsHeaderCard::read(void*, std::string&)" | |||
45 | #define G_WRITE"GFitsHeaderCard::write(void*)" "GFitsHeaderCard::write(void*)" | |||
46 | ||||
47 | /* __ Definitions ________________________________________________________ */ | |||
48 | ||||
49 | /* __ Macros _____________________________________________________________ */ | |||
50 | ||||
51 | /* __ Coding definitions _________________________________________________ */ | |||
52 | ||||
53 | /* __ Enumerations _______________________________________________________ */ | |||
54 | ||||
55 | /* __ Debug definitions __________________________________________________ */ | |||
56 | ||||
57 | ||||
58 | /*========================================================================== | |||
59 | = = | |||
60 | = Constructors/destructors = | |||
61 | = = | |||
62 | ==========================================================================*/ | |||
63 | ||||
64 | /***********************************************************************//** | |||
65 | * @brief Void constructor | |||
66 | ***************************************************************************/ | |||
67 | GFitsHeaderCard::GFitsHeaderCard(void) | |||
68 | { | |||
69 | // Initialise class members | |||
70 | init_members(); | |||
71 | ||||
72 | // Return | |||
73 | return; | |||
74 | } | |||
75 | ||||
76 | ||||
77 | /***********************************************************************//** | |||
78 | * @brief Constructor for string cards | |||
79 | * | |||
80 | * @param[in] keyname Card name. | |||
81 | * @param[in] value Card string value. | |||
82 | * @param[in] comment Card comment. | |||
83 | * | |||
84 | * This constructor builds a header card from the keyname, value and comment. | |||
85 | ***************************************************************************/ | |||
86 | GFitsHeaderCard::GFitsHeaderCard(const std::string& keyname, | |||
87 | const std::string& value, | |||
88 | const std::string& comment) | |||
89 | { | |||
90 | // Initialise class members | |||
91 | init_members(); | |||
92 | ||||
93 | // Set members | |||
94 | this->keyname(keyname); | |||
95 | this->value("'"+value+"'"); | |||
96 | this->comment(comment); | |||
97 | ||||
98 | // Return | |||
99 | return; | |||
100 | } | |||
101 | ||||
102 | ||||
103 | /***********************************************************************//** | |||
104 | * @brief Constructor for floating point cards | |||
105 | * | |||
106 | * @param[in] keyname Card name. | |||
107 | * @param[in] value Card floating point value. | |||
108 | * @param[in] comment Card comment. | |||
109 | * | |||
110 | * This constructor builds a header card from the keyname, value and comment. | |||
111 | ***************************************************************************/ | |||
112 | GFitsHeaderCard::GFitsHeaderCard(const std::string& keyname, | |||
113 | const double& value, | |||
114 | const std::string& comment) | |||
115 | { | |||
116 | // Initialise class members | |||
117 | init_members(); | |||
118 | ||||
119 | // Set members | |||
120 | this->keyname(keyname); | |||
121 | this->value(value); | |||
122 | this->comment(comment); | |||
123 | ||||
124 | // Return | |||
125 | return; | |||
126 | } | |||
127 | ||||
128 | ||||
129 | /***********************************************************************//** | |||
130 | * @brief Constructor for integer cards | |||
131 | * | |||
132 | * @param[in] keyname Card name. | |||
133 | * @param[in] value Card integer value. | |||
134 | * @param[in] comment Card comment. | |||
135 | * | |||
136 | * This constructor builds a header card from the keyname, value and comment. | |||
137 | ***************************************************************************/ | |||
138 | GFitsHeaderCard::GFitsHeaderCard(const std::string& keyname, | |||
139 | const int& value, | |||
140 | const std::string& comment) | |||
141 | { | |||
142 | // Initialise class members | |||
143 | init_members(); | |||
144 | ||||
145 | // Set members | |||
146 | this->keyname(keyname); | |||
147 | this->value(value); | |||
148 | this->comment(comment); | |||
149 | ||||
150 | // Return | |||
151 | return; | |||
152 | } | |||
153 | ||||
154 | ||||
155 | /***********************************************************************//** | |||
156 | * @brief Copy constructor | |||
157 | * | |||
158 | * @param[in] card Header card. | |||
159 | ***************************************************************************/ | |||
160 | GFitsHeaderCard::GFitsHeaderCard(const GFitsHeaderCard& card) | |||
161 | { | |||
162 | // Initialise class members for clean destruction | |||
163 | init_members(); | |||
164 | ||||
165 | // Copy members | |||
166 | copy_members(card); | |||
167 | ||||
168 | // Return | |||
169 | return; | |||
170 | } | |||
171 | ||||
172 | ||||
173 | /***********************************************************************//** | |||
174 | * @brief Destructor | |||
175 | ***************************************************************************/ | |||
176 | GFitsHeaderCard::~GFitsHeaderCard(void) | |||
177 | { | |||
178 | // Free members | |||
179 | free_members(); | |||
180 | ||||
181 | // Return | |||
182 | return; | |||
183 | } | |||
184 | ||||
185 | /*========================================================================== | |||
186 | = = | |||
187 | = Operators = | |||
188 | = = | |||
189 | ==========================================================================*/ | |||
190 | ||||
191 | /***********************************************************************//** | |||
192 | * @brief Assignment operator | |||
193 | * | |||
194 | * @param[in] card Header card. | |||
195 | * @return Header card. | |||
196 | ***************************************************************************/ | |||
197 | GFitsHeaderCard& GFitsHeaderCard::operator=(const GFitsHeaderCard& card) | |||
198 | { | |||
199 | // Execute only if object is not identical | |||
200 | if (this != &card) { | |||
201 | ||||
202 | // Free members | |||
203 | free_members(); | |||
204 | ||||
205 | // Initialise private members for clean destruction | |||
206 | init_members(); | |||
207 | ||||
208 | // Copy members | |||
209 | copy_members(card); | |||
210 | ||||
211 | } // endif: object was not identical | |||
212 | ||||
213 | // Return this object | |||
214 | return *this; | |||
215 | } | |||
216 | ||||
217 | ||||
218 | /*========================================================================== | |||
219 | = = | |||
220 | = Public methods = | |||
221 | = = | |||
222 | ==========================================================================*/ | |||
223 | ||||
224 | /***********************************************************************//** | |||
225 | * @brief Clear header card | |||
226 | ***************************************************************************/ | |||
227 | void GFitsHeaderCard::clear(void) | |||
228 | { | |||
229 | // Free members | |||
230 | free_members(); | |||
231 | ||||
232 | // Initialise members | |||
233 | init_members(); | |||
234 | ||||
235 | // Return | |||
236 | return; | |||
237 | } | |||
238 | ||||
239 | ||||
240 | /***********************************************************************//** | |||
241 | * @brief Clone header card | |||
242 | * | |||
243 | * @return Pointer to deep copy of header card. | |||
244 | ***************************************************************************/ | |||
245 | GFitsHeaderCard* GFitsHeaderCard::clone(void) const | |||
246 | { | |||
247 | return new GFitsHeaderCard(*this); | |||
248 | } | |||
249 | ||||
250 | ||||
251 | /***********************************************************************//** | |||
252 | * @brief Set name of header card | |||
253 | * | |||
254 | * @param[in] keyname Card name. | |||
255 | ***************************************************************************/ | |||
256 | void GFitsHeaderCard::keyname(const std::string& keyname) | |||
257 | { | |||
258 | // Set name of card | |||
259 | m_keyname = keyname; | |||
260 | ||||
261 | // Return | |||
262 | return; | |||
263 | } | |||
264 | ||||
265 | ||||
266 | /***********************************************************************//** | |||
267 | * @brief Set string value of header card | |||
268 | * | |||
269 | * @param[in] value Card string value. | |||
270 | * | |||
271 | * This method sets the value of a string header card. The internal string | |||
272 | * representation contains hyphens, yet for keyword writing the hyphens are | |||
273 | * stripped. | |||
274 | ***************************************************************************/ | |||
275 | void GFitsHeaderCard::value(const std::string& value) | |||
276 | { | |||
277 | // Free data type | |||
278 | free_dtype(); | |||
279 | ||||
280 | // Set value | |||
281 | m_value = value; | |||
282 | ||||
283 | // Attach hyphens to internal string representation if required | |||
284 | if (m_value[0] != '\x27') { | |||
285 | m_value = "'" + m_value; | |||
286 | } | |||
287 | if (m_value[m_value.length()-1] != '\x27') { | |||
288 | m_value = m_value + "'"; | |||
289 | } | |||
290 | ||||
291 | // Strip hyphens and whitespace from datatype value that is used for | |||
292 | // keyword writing | |||
293 | std::string value_dtype = | |||
294 | gammalib::strip_whitespace(m_value.substr(1, m_value.length() - 2)); | |||
295 | ||||
296 | // Set data type | |||
297 | m_dtype = __TSTRING16; | |||
298 | m_value_dtype = new std::string(value_dtype); | |||
299 | ||||
300 | // Return | |||
301 | return; | |||
302 | } | |||
303 | ||||
304 | ||||
305 | /***********************************************************************//** | |||
306 | * @brief Set boolean value of header card | |||
307 | * | |||
308 | * @param[in] value Card boolean value. | |||
309 | ***************************************************************************/ | |||
310 | void GFitsHeaderCard::value(const bool& value) | |||
311 | { | |||
312 | // Free data type | |||
313 | free_dtype(); | |||
314 | ||||
315 | // Set value and data type | |||
316 | m_value = (value) ? "T" : "F"; | |||
317 | m_dtype = __TLOGICAL14; | |||
318 | m_value_dtype = new bool(value); | |||
319 | ||||
320 | // Return | |||
321 | return; | |||
322 | } | |||
323 | ||||
324 | ||||
325 | /***********************************************************************//** | |||
326 | * @brief Set single precision value of header card | |||
327 | * | |||
328 | * @param[in] value Card single precision value. | |||
329 | ***************************************************************************/ | |||
330 | void GFitsHeaderCard::value(const float& value) | |||
331 | { | |||
332 | // Free data type | |||
333 | free_dtype(); | |||
334 | ||||
335 | // Set value and data type | |||
336 | m_value = gammalib::str(value); | |||
337 | m_dtype = __TFLOAT42; | |||
338 | m_value_dtype = new float(value); | |||
339 | ||||
340 | // Return | |||
341 | return; | |||
342 | } | |||
343 | ||||
344 | ||||
345 | /***********************************************************************//** | |||
346 | * @brief Set double precision value of header card | |||
347 | * | |||
348 | * @param[in] value Card double precision value. | |||
349 | ***************************************************************************/ | |||
350 | void GFitsHeaderCard::value(const double& value) | |||
351 | { | |||
352 | // Free data type | |||
353 | free_dtype(); | |||
354 | ||||
355 | // Set value and data type | |||
356 | m_value = gammalib::str(value); | |||
357 | m_dtype = __TDOUBLE82; | |||
358 | m_value_dtype = new double(value); | |||
359 | ||||
360 | // Return | |||
361 | return; | |||
362 | } | |||
363 | ||||
364 | ||||
365 | /***********************************************************************//** | |||
366 | * @brief Set unsigned short integer value of header card | |||
367 | * | |||
368 | * @param[in] value Card unsigned short integer value. | |||
369 | ***************************************************************************/ | |||
370 | void GFitsHeaderCard::value(const unsigned short& value) | |||
371 | { | |||
372 | // Free data type | |||
373 | free_dtype(); | |||
374 | ||||
375 | // Set value and data type | |||
376 | m_value = gammalib::str(value); | |||
377 | m_dtype = __TUSHORT20; | |||
378 | m_value_dtype = new unsigned short(value); | |||
379 | ||||
380 | // Return | |||
381 | return; | |||
382 | } | |||
383 | ||||
384 | ||||
385 | /***********************************************************************//** | |||
386 | * @brief Set short integer value of header card | |||
387 | * | |||
388 | * @param[in] value Card short integer value. | |||
389 | ***************************************************************************/ | |||
390 | void GFitsHeaderCard::value(const short& value) | |||
391 | { | |||
392 | // Free data type | |||
393 | free_dtype(); | |||
394 | ||||
395 | // Set value and data type | |||
396 | m_value = gammalib::str(value); | |||
397 | m_dtype = __TSHORT21; | |||
398 | m_value_dtype = new short(value); | |||
399 | ||||
400 | // Return | |||
401 | return; | |||
402 | } | |||
403 | ||||
404 | ||||
405 | /***********************************************************************//** | |||
406 | * @brief Set unsigned integer value of header card | |||
407 | * | |||
408 | * @param[in] value Card unsigned integer value. | |||
409 | ***************************************************************************/ | |||
410 | void GFitsHeaderCard::value(const unsigned int& value) | |||
411 | { | |||
412 | // Free data type | |||
413 | free_dtype(); | |||
414 | ||||
415 | // Set value and data type | |||
416 | m_value = gammalib::str(value); | |||
417 | m_dtype = __TUINT30; | |||
418 | m_value_dtype = new unsigned int(value); | |||
419 | ||||
420 | // Return | |||
421 | return; | |||
422 | } | |||
423 | ||||
424 | ||||
425 | /***********************************************************************//** | |||
426 | * @brief Set integer value of header card | |||
427 | * | |||
428 | * @param[in] value Card integer value. | |||
429 | ***************************************************************************/ | |||
430 | void GFitsHeaderCard::value(const int& value) | |||
431 | { | |||
432 | // Free data type | |||
433 | free_dtype(); | |||
434 | ||||
435 | // Set value and data type | |||
436 | m_value = gammalib::str(value); | |||
437 | m_dtype = __TINT31; | |||
438 | m_value_dtype = new int(value); | |||
439 | ||||
440 | // Return | |||
441 | return; | |||
442 | } | |||
443 | ||||
444 | ||||
445 | /***********************************************************************//** | |||
446 | * @brief Set long integer value of header card | |||
447 | * | |||
448 | * @param[in] value Card long integer value. | |||
449 | ***************************************************************************/ | |||
450 | void GFitsHeaderCard::value(const long& value) | |||
451 | { | |||
452 | // Free data type | |||
453 | free_dtype(); | |||
454 | ||||
455 | // Set value and data type | |||
456 | m_value = gammalib::str(value); | |||
457 | m_dtype = __TLONG41; | |||
458 | m_value_dtype = new long(value); | |||
459 | ||||
460 | // Return | |||
461 | return; | |||
462 | } | |||
463 | ||||
464 | ||||
465 | /***********************************************************************//** | |||
466 | * @brief Set unsigned integer long value of header card | |||
467 | * | |||
468 | * @param[in] value Card unsigned long integer value. | |||
469 | ***************************************************************************/ | |||
470 | void GFitsHeaderCard::value(const unsigned long& value) | |||
471 | { | |||
472 | // Free data type | |||
473 | free_dtype(); | |||
474 | ||||
475 | // Set value and data type | |||
476 | m_value = gammalib::str(value); | |||
477 | m_dtype = __TULONG40; | |||
478 | m_value_dtype = new unsigned long(value); | |||
479 | ||||
480 | // Return | |||
481 | return; | |||
482 | } | |||
483 | ||||
484 | ||||
485 | /***********************************************************************//** | |||
486 | * @brief Set long long integer value of header card | |||
487 | * | |||
488 | * @param[in] value Card long long integer value. | |||
489 | ***************************************************************************/ | |||
490 | void GFitsHeaderCard::value(const long long& value) | |||
491 | { | |||
492 | // Free data type | |||
493 | free_dtype(); | |||
494 | ||||
495 | // Set value and data type | |||
496 | m_value = gammalib::str(value); | |||
497 | m_dtype = __TLONGLONG81; | |||
498 | m_value_dtype = new long long(value); | |||
499 | ||||
500 | // Return | |||
501 | return; | |||
502 | } | |||
503 | ||||
504 | ||||
505 | /***********************************************************************//** | |||
506 | * @brief Return header card value as string | |||
507 | * | |||
508 | * Convert header card value into a string. | |||
509 | * Any hyphens that may occur in the FITS card will be automatically stripped. | |||
510 | ***************************************************************************/ | |||
511 | std::string GFitsHeaderCard::string(void) const | |||
512 | { | |||
513 | // Initialize return value to actual value string | |||
514 | std::string result = m_value; | |||
515 | ||||
516 | // Type dependent conversion | |||
517 | if (m_value_dtype != NULL__null) { | |||
518 | switch (m_dtype) { | |||
519 | case __TSTRING16: | |||
520 | if (m_value.length() > 2) { | |||
521 | result = gammalib::strip_whitespace(m_value.substr(1, m_value.length() - 2)); | |||
522 | } | |||
523 | break; | |||
524 | default: | |||
525 | break; | |||
526 | } | |||
527 | } | |||
528 | ||||
529 | // Return string | |||
530 | return result; | |||
531 | ||||
532 | } | |||
533 | ||||
534 | ||||
535 | /***********************************************************************//** | |||
536 | * @brief Return header card value as double precision | |||
537 | * | |||
538 | * Convert header card value into a double precision value. In case that the | |||
539 | * card did not contain a numerical value, 0 will be returned by the | |||
540 | * method. | |||
541 | ***************************************************************************/ | |||
542 | double GFitsHeaderCard::real(void) const | |||
543 | { | |||
544 | // Initialize return value to 0.0 | |||
545 | double result = 0.0; | |||
546 | ||||
547 | // Type dependent conversion | |||
548 | if (m_value_dtype != NULL__null) { | |||
549 | switch (m_dtype) { | |||
550 | case __TSTRING16: | |||
551 | if (m_value.length() > 2) { | |||
552 | result = gammalib::todouble(m_value.substr(1, m_value.length() - 2)); | |||
553 | } | |||
554 | break; | |||
555 | case __TLOGICAL14: | |||
556 | result = (m_value == "T") ? 1.0 : 0.0; | |||
557 | break; | |||
558 | default: | |||
559 | result = gammalib::todouble(m_value); | |||
560 | break; | |||
561 | } | |||
562 | } | |||
563 | ||||
564 | // Return string | |||
565 | return result; | |||
566 | ||||
567 | } | |||
568 | ||||
569 | ||||
570 | /***********************************************************************//** | |||
571 | * @brief Return header card value as integer | |||
572 | * | |||
573 | * Convert header card value into a integer value. In case that the | |||
574 | * card did not contain a numerical value, 0 will be returned by the | |||
575 | * method. | |||
576 | ***************************************************************************/ | |||
577 | int GFitsHeaderCard::integer(void) const | |||
578 | { | |||
579 | // Initialize return value to 0 | |||
580 | int result = 0; | |||
581 | ||||
582 | // Type dependent conversion | |||
583 | if (m_value_dtype != NULL__null) { | |||
584 | switch (m_dtype) { | |||
585 | case __TSTRING16: | |||
586 | if (m_value.length() > 2) { | |||
587 | result = gammalib::toint(m_value.substr(1, m_value.length() - 2)); | |||
588 | } | |||
589 | break; | |||
590 | case __TLOGICAL14: | |||
591 | result = (m_value == "T") ? 1 : 0; | |||
592 | break; | |||
593 | default: | |||
594 | result = gammalib::toint(m_value); | |||
595 | break; | |||
596 | } | |||
597 | } | |||
598 | ||||
599 | // Return string | |||
600 | return result; | |||
601 | ||||
602 | } | |||
603 | ||||
604 | ||||
605 | /***********************************************************************//** | |||
606 | * @brief Print header card information | |||
607 | * | |||
608 | * @param[in] chatter Chattiness (defaults to NORMAL). | |||
609 | * @return String containing header card information. | |||
610 | ***************************************************************************/ | |||
611 | std::string GFitsHeaderCard::print(const GChatter& chatter) const | |||
612 | { | |||
613 | // Initialise result string | |||
614 | std::string result; | |||
615 | ||||
616 | // Continue only if chatter is not silent | |||
617 | if (chatter != SILENT) { | |||
618 | ||||
619 | // Append keyname | |||
620 | result.append(gammalib::left(m_keyname,8)); | |||
621 | ||||
622 | // Format values | |||
623 | if (m_keyname != "COMMENT" && m_keyname != "HISTORY" && m_keyname != "") { | |||
624 | if (m_unit.length() > 0) { | |||
625 | result.append(" ="+gammalib::right(m_value,21)+" / ["+m_unit+"] "+m_comment); | |||
626 | } | |||
627 | else { | |||
628 | result.append(" ="+gammalib::right(m_value,21)+" / "+m_comment); | |||
629 | } | |||
630 | } | |||
631 | else { | |||
632 | result.append(" "+m_comment); | |||
633 | } | |||
634 | ||||
635 | // Attach card type | |||
636 | if (m_value_dtype != NULL__null) { | |||
637 | switch (m_dtype) { | |||
638 | case __TNULL0: | |||
639 | result.append(" <null>"); | |||
640 | break; | |||
641 | case __TBIT1: | |||
642 | result.append(" <bit>"); | |||
643 | break; | |||
644 | case __TBYTE11: | |||
645 | result.append(" <byte>"); | |||
646 | break; | |||
647 | case __TSBYTE12: | |||
648 | result.append(" <signed byte>"); | |||
649 | break; | |||
650 | case __TLOGICAL14: | |||
651 | result.append(" <bool>"); | |||
652 | break; | |||
653 | case __TSTRING16: | |||
654 | result.append(" <string>"); | |||
655 | break; | |||
656 | case __TUSHORT20: | |||
657 | result.append(" <unsigned short>"); | |||
658 | break; | |||
659 | case __TSHORT21: | |||
660 | result.append(" <short>"); | |||
661 | break; | |||
662 | case __TUINT30: | |||
663 | result.append(" <unsigned int>"); | |||
664 | break; | |||
665 | case __TINT31: | |||
666 | result.append(" <int>"); | |||
667 | break; | |||
668 | case __TULONG40: | |||
669 | result.append(" <unsigned long>"); | |||
670 | break; | |||
671 | case __TLONG41: | |||
672 | result.append(" <long>"); | |||
673 | break; | |||
674 | case __TLONGLONG81: | |||
675 | result.append(" <long long>"); | |||
676 | break; | |||
677 | case __TFLOAT42: | |||
678 | result.append(" <float>"); | |||
679 | break; | |||
680 | case __TDOUBLE82: | |||
681 | result.append(" <double>"); | |||
682 | break; | |||
683 | case __TCOMPLEX83: | |||
684 | result.append(" <complex>"); | |||
685 | break; | |||
686 | case __TDBLCOMPLEX163: | |||
687 | result.append(" <double complex>"); | |||
688 | break; | |||
689 | default: | |||
690 | result.append(" <unsupported value "+gammalib::str(m_dtype)+">"); | |||
691 | break; | |||
692 | } | |||
693 | } | |||
694 | /* | |||
695 | else { | |||
696 | switch (m_dtype) { | |||
697 | case __TNULL: | |||
698 | result.append(" <null>"); | |||
699 | break; | |||
700 | default: | |||
701 | result.append(" <non native>"); | |||
702 | break; | |||
703 | } | |||
704 | } | |||
705 | */ | |||
706 | ||||
707 | } // endif: chatter was not silent | |||
708 | ||||
709 | // Return result | |||
710 | return result; | |||
711 | } | |||
712 | ||||
713 | ||||
714 | /*========================================================================== | |||
715 | = = | |||
716 | = Private methods = | |||
717 | = = | |||
718 | ==========================================================================*/ | |||
719 | ||||
720 | /***********************************************************************//** | |||
721 | * @brief Initialise class members | |||
722 | ***************************************************************************/ | |||
723 | void GFitsHeaderCard::init_members(void) | |||
724 | { | |||
725 | // Initialise members | |||
726 | m_keyname.clear(); | |||
727 | m_value.clear(); | |||
728 | m_unit.clear(); | |||
729 | m_comment.clear(); | |||
730 | m_value_dtype = NULL__null; | |||
731 | m_dtype = __TNULL0; | |||
732 | m_value_decimals = 10; | |||
733 | m_comment_write = true; // Was false before, not sure why ... | |||
734 | ||||
735 | // Return | |||
736 | return; | |||
737 | } | |||
738 | ||||
739 | ||||
740 | /***********************************************************************//** | |||
741 | * @brief Copy class members | |||
742 | * | |||
743 | * @param[in] card Header card to be copied | |||
744 | ***************************************************************************/ | |||
745 | void GFitsHeaderCard::copy_members(const GFitsHeaderCard& card) | |||
746 | { | |||
747 | // Copy members | |||
748 | m_keyname = card.m_keyname; | |||
749 | m_value = card.m_value; | |||
750 | m_value_decimals = card.m_value_decimals; | |||
751 | m_unit = card.m_unit; | |||
752 | m_comment = card.m_comment; | |||
753 | m_comment_write = card.m_comment_write; | |||
754 | ||||
755 | // Copy native data types | |||
756 | copy_dtype(card); | |||
757 | ||||
758 | // Return | |||
759 | return; | |||
760 | } | |||
761 | ||||
762 | ||||
763 | /***********************************************************************//** | |||
764 | * @brief Delete class members | |||
765 | ***************************************************************************/ | |||
766 | void GFitsHeaderCard::free_members(void) | |||
767 | { | |||
768 | // Free members | |||
769 | free_dtype(); | |||
770 | ||||
771 | // Return | |||
772 | return; | |||
773 | } | |||
774 | ||||
775 | ||||
776 | /***********************************************************************//** | |||
777 | * @brief Copy dtype | |||
778 | * | |||
779 | * @param[in] card Header card. | |||
780 | * | |||
781 | * Copies the data type of a header card. | |||
782 | ***************************************************************************/ | |||
783 | void GFitsHeaderCard::copy_dtype(const GFitsHeaderCard& card) | |||
784 | { | |||
785 | // Copy data type | |||
786 | if (card.m_value_dtype != NULL__null) { | |||
787 | m_dtype = card.m_dtype; | |||
788 | switch (m_dtype) { | |||
789 | case __TLOGICAL14: | |||
790 | m_value_dtype = new bool(*((bool*)card.m_value_dtype)); | |||
791 | break; | |||
792 | case __TSTRING16: | |||
793 | m_value_dtype = new std::string(*((std::string*)card.m_value_dtype)); | |||
794 | break; | |||
795 | case __TUSHORT20: | |||
796 | m_value_dtype = new unsigned short(*((unsigned short*)card.m_value_dtype)); | |||
797 | break; | |||
798 | case __TSHORT21: | |||
799 | m_value_dtype = new short(*((short*)card.m_value_dtype)); | |||
800 | break; | |||
801 | case __TUINT30: | |||
802 | m_value_dtype = new unsigned int(*((unsigned int*)card.m_value_dtype)); | |||
803 | break; | |||
804 | case __TINT31: | |||
805 | m_value_dtype = new int(*((int*)card.m_value_dtype)); | |||
806 | break; | |||
807 | case __TULONG40: | |||
808 | m_value_dtype = new unsigned long(*((unsigned long*)card.m_value_dtype)); | |||
809 | break; | |||
810 | case __TLONG41: | |||
811 | m_value_dtype = new long(*((long*)card.m_value_dtype)); | |||
812 | break; | |||
813 | case __TLONGLONG81: | |||
814 | m_value_dtype = new long long(*((long long*)card.m_value_dtype)); | |||
815 | break; | |||
816 | case __TFLOAT42: | |||
817 | m_value_dtype = new float(*((float*)card.m_value_dtype)); | |||
818 | break; | |||
819 | case __TDOUBLE82: | |||
820 | m_value_dtype = new double(*((double*)card.m_value_dtype)); | |||
821 | break; | |||
822 | default: | |||
823 | std::string msg = "Invalid data type code "+ | |||
824 | gammalib::str(m_dtype)+" encountered."; | |||
825 | gammalib::warning(G_COPY_DTYPE"GFitsHeaderCard::copy_dtype(GFitsHeaderCard&)", msg); | |||
826 | break; | |||
827 | } | |||
828 | } | |||
829 | ||||
830 | // Return | |||
831 | return; | |||
832 | } | |||
833 | ||||
834 | ||||
835 | /***********************************************************************//** | |||
836 | * @brief Free dtype | |||
837 | ***************************************************************************/ | |||
838 | void GFitsHeaderCard::free_dtype(void) | |||
839 | { | |||
840 | // Free data type | |||
841 | if (m_value_dtype != NULL__null) { | |||
842 | switch (m_dtype) { | |||
843 | case __TLOGICAL14: | |||
844 | delete (bool*)m_value_dtype; | |||
845 | break; | |||
846 | case __TSTRING16: | |||
847 | delete (std::string*)m_value_dtype; | |||
848 | break; | |||
849 | case __TUSHORT20: | |||
850 | delete (unsigned short*)m_value_dtype; | |||
851 | break; | |||
852 | case __TSHORT21: | |||
853 | delete (short*)m_value_dtype; | |||
854 | break; | |||
855 | case __TUINT30: | |||
856 | delete (unsigned int*)m_value_dtype; | |||
857 | break; | |||
858 | case __TINT31: | |||
859 | delete (int*)m_value_dtype; | |||
860 | break; | |||
861 | case __TULONG40: | |||
862 | delete (unsigned long*)m_value_dtype; | |||
| ||||
863 | break; | |||
864 | case __TLONG41: | |||
865 | delete (long*)m_value_dtype; | |||
866 | break; | |||
867 | case __TLONGLONG81: | |||
868 | delete (long long*)m_value_dtype; | |||
869 | break; | |||
870 | case __TFLOAT42: | |||
871 | delete (float*)m_value_dtype; | |||
872 | break; | |||
873 | case __TDOUBLE82: | |||
874 | delete (double*)m_value_dtype; | |||
875 | break; | |||
876 | default: | |||
877 | std::string msg = "Invalid data type code "+ | |||
878 | gammalib::str(m_dtype)+" encountered."; | |||
879 | gammalib::warning(G_FREE_DTYPE"GFitsHeaderCard::free_dtype()", msg); | |||
880 | break; | |||
881 | } | |||
882 | } | |||
883 | ||||
884 | // Return | |||
885 | return; | |||
886 | } | |||
887 | ||||
888 | ||||
889 | /***********************************************************************//** | |||
890 | * @brief Set native data type from card string | |||
891 | * | |||
892 | * @param[in] value Card string. | |||
893 | * | |||
894 | * The native data type is determined from the card string. This method sets | |||
895 | * the members m_dtype and m_value_type. The card type is determined by | |||
896 | * analyzing the card value. | |||
897 | * | |||
898 | * @todo Implement syntax checking for integer or float values. | |||
899 | ***************************************************************************/ | |||
900 | void GFitsHeaderCard::set_dtype(const std::string& value) | |||
901 | { | |||
902 | // Free data type | |||
903 | free_dtype(); | |||
904 | ||||
905 | // Main loop to allow fall through | |||
906 | do { | |||
907 | ||||
908 | // Get index of last string element | |||
909 | int last = m_value.length() - 1; | |||
910 | ||||
911 | // If value is empty and there is a COMMENT, HISTORY or BLANKFIELD | |||
912 | // (empty) keyword then we have a commentary card. We can just | |||
913 | // skip this card here. Otherwise we have an undefined value, also | |||
914 | // called NULL value. | |||
915 | if (last < 0) { | |||
916 | if (m_keyname == "COMMENT" || | |||
917 | m_keyname == "HISTORY" || | |||
918 | m_keyname == "") { | |||
919 | continue; | |||
920 | } | |||
921 | else { | |||
922 | m_dtype = __TNULL0; | |||
923 | continue; | |||
924 | } | |||
925 | } | |||
926 | ||||
927 | // If value is enclosed in parentheses then we have a string | |||
928 | if (m_value[0] == '\x27' && m_value[last] == '\x27') { | |||
929 | this->value(value); | |||
930 | continue; | |||
931 | } | |||
932 | ||||
933 | // If value has only one digit and is either 'F' or 'T' we have a | |||
934 | // Boolean | |||
935 | if (last == 0 && (m_value[0] == 'F' || m_value[0] == 'T')) { | |||
936 | this->value((m_value[0] == 'T')); | |||
937 | continue; | |||
938 | } | |||
939 | ||||
940 | // Conversion | |||
941 | double value_dbl = gammalib::todouble(m_value); | |||
942 | long long value_ll = gammalib::tolonglong(m_value); | |||
943 | unsigned long long value_ull = gammalib::toulonglong(m_value); | |||
944 | ||||
945 | // Check if we have an integer | |||
946 | if ((value_dbl >= 0 && value_dbl == value_ull) || | |||
947 | (value_dbl < 0 && value_dbl == value_ll)) { | |||
948 | ||||
949 | // Consider positive integers as unsigned | |||
950 | if (value_dbl >= 0) { | |||
951 | if (value_ull > ULONG_MAX(9223372036854775807L *2UL+1UL)) { | |||
952 | m_dtype = __TLONGLONG81; | |||
953 | m_value_dtype = new long long(value_ll); | |||
954 | } | |||
955 | else if (value_ull > USHRT_MAX(32767 *2 +1)) { | |||
956 | m_dtype = __TULONG40; | |||
957 | m_value_dtype = new unsigned long(value_ull); | |||
958 | } | |||
959 | else { | |||
960 | m_dtype = __TUSHORT20; | |||
961 | m_value_dtype = new unsigned short(value_ull); | |||
962 | } | |||
963 | } | |||
964 | ||||
965 | // ... otherwise consider signed | |||
966 | else { | |||
967 | if (value_ll > LONG_MAX9223372036854775807L || value_ll < LONG_MIN(-9223372036854775807L -1L)) { | |||
968 | m_dtype = __TLONGLONG81; | |||
969 | m_value_dtype = new long long(value_ll); | |||
970 | } | |||
971 | else if (value_ll > SHRT_MAX32767 || value_ll < SHRT_MIN(-32767 -1)) { | |||
972 | m_dtype = __TLONG41; | |||
973 | m_value_dtype = new long(value_ll); | |||
974 | } | |||
975 | else { | |||
976 | m_dtype = __TSHORT21; | |||
977 | m_value_dtype = new short(value_ll); | |||
978 | } | |||
979 | } | |||
980 | } // endif: handled integers | |||
981 | ||||
982 | // ... otherwise handle floats | |||
983 | else { | |||
984 | if (value_dbl > FLT_MAX3.40282347e+38F || value_dbl < FLT_MIN1.17549435e-38F) { | |||
985 | m_dtype = __TDOUBLE82; | |||
986 | m_value_dtype = new double(value_dbl); | |||
987 | } | |||
988 | else { | |||
989 | m_dtype = __TFLOAT42; | |||
990 | m_value_dtype = new float(value_dbl); | |||
991 | } | |||
992 | } | |||
993 | ||||
994 | } while(0); | |||
995 | ||||
996 | // Return | |||
997 | return; | |||
998 | } | |||
999 | ||||
1000 | ||||
1001 | /***********************************************************************//** | |||
1002 | * @brief Read header card from FITS file | |||
1003 | * | |||
1004 | * @param[in] vptr FITS file void pointer. | |||
1005 | * @param[in] keynum Number of the header card. | |||
1006 | ***************************************************************************/ | |||
1007 | void GFitsHeaderCard::read(void* vptr, const int& keynum) | |||
1008 | { | |||
1009 | // Initialise status | |||
1010 | int status = 0; | |||
1011 | ||||
1012 | // Move to HDU | |||
1013 | gammalib::fits_move_to_hdu(G_READ_NUM"GFitsHeaderCard::read(void*, int&)", vptr); | |||
1014 | ||||
1015 | // Read keyword | |||
1016 | char keyname[80]; | |||
1017 | char value[80]; | |||
1018 | char comment[80]; | |||
1019 | status = __ffgkyn(FPTR(vptr), keynum, keyname, value, comment, &status)ffgkyn(((__fitsfile*)vptr), keynum, keyname, value, comment, & status); | |||
1020 | if (status != 0) { | |||
1021 | throw GException::fits_error(G_READ_NUM"GFitsHeaderCard::read(void*, int&)", status); | |||
1022 | } | |||
1023 | ||||
1024 | // Store result | |||
1025 | m_keyname.assign(keyname); | |||
1026 | m_value.assign(value); | |||
1027 | m_comment.assign(comment); | |||
1028 | ||||
1029 | // Determine card type | |||
1030 | set_dtype(m_value); | |||
1031 | ||||
1032 | // Return | |||
1033 | return; | |||
1034 | } | |||
1035 | ||||
1036 | ||||
1037 | /***********************************************************************//** | |||
1038 | * @brief Read header card from FITS file | |||
1039 | * | |||
1040 | * @param[in] vptr FITS file void pointer. | |||
1041 | * @param[in] keyname Name of the header card. | |||
1042 | * | |||
1043 | * @exception GException::invalid_value | |||
1044 | * Specified @p keyname not found in FITS header. | |||
1045 | * @exception GException::fits_error | |||
1046 | * cfitsio error occured. | |||
1047 | ***************************************************************************/ | |||
1048 | void GFitsHeaderCard::read(void* vptr, const std::string& keyname) | |||
1049 | { | |||
1050 | // Initialise FITS status | |||
1051 | int status = 0; | |||
1052 | ||||
1053 | // Move to HDU | |||
1054 | gammalib::fits_move_to_hdu(G_READ_STR"GFitsHeaderCard::read(void*, std::string&)", vptr); | |||
1055 | ||||
1056 | // Read keyword | |||
1057 | char value[80]; | |||
1058 | char comment[80]; | |||
1059 | status = __ffgkey(FPTR(vptr), (char*)keyname.c_str(), value, comment,ffgkey(((__fitsfile*)vptr), (char*)keyname.c_str(), value, comment , &status) | |||
1060 | &status)ffgkey(((__fitsfile*)vptr), (char*)keyname.c_str(), value, comment , &status); | |||
1061 | ||||
1062 | // Catch error | |||
1063 | if (status == 202) { // Keyword not found | |||
| ||||
1064 | std::string msg = "Header card with keyword \""+keyname+"\" not" | |||
1065 | " found in FITS header (status=202)."; | |||
1066 | throw GException::invalid_value(G_READ_STR"GFitsHeaderCard::read(void*, std::string&)", msg); | |||
1067 | } | |||
1068 | else if (status != 0) { // Any other error | |||
1069 | std::string msg = "Unable to read keyword \""+keyname+"\" from" | |||
1070 | " FITS extension "+ | |||
1071 | gammalib::str((FPTR(vptr)((__fitsfile*)vptr)->HDUposition))+ | |||
1072 | " header."; | |||
1073 | throw GException::fits_error(G_READ_STR"GFitsHeaderCard::read(void*, std::string&)", status, msg); | |||
1074 | } | |||
1075 | ||||
1076 | // Store result | |||
1077 | m_keyname = keyname; | |||
1078 | m_value.assign(value); | |||
1079 | m_comment.assign(comment); | |||
1080 | ||||
1081 | // Determine card type | |||
1082 | set_dtype(m_value); | |||
1083 | ||||
1084 | // Return | |||
1085 | return; | |||
1086 | } | |||
1087 | ||||
1088 | ||||
1089 | /***********************************************************************//** | |||
1090 | * @brief Write header card | |||
1091 | * | |||
1092 | * @param[in] vptr FITS file void pointer. | |||
1093 | * | |||
1094 | * Writes any kind of header card to a FITS file. | |||
1095 | ***************************************************************************/ | |||
1096 | void GFitsHeaderCard::write(void* vptr) const | |||
1097 | { | |||
1098 | // Initialise status | |||
1099 | int status = 0; | |||
1100 | ||||
1101 | // Move to HDU | |||
1102 | gammalib::fits_move_to_hdu(G_WRITE"GFitsHeaderCard::write(void*)", vptr); | |||
1103 | ||||
1104 | // If card is comment then write comment | |||
1105 | if (m_keyname == "COMMENT") { | |||
1106 | if (m_comment_write) { | |||
1107 | status = __ffpcom(FPTR(vptr), (char*)m_comment.c_str(), &status)ffpcom(((__fitsfile*)vptr), (char*)m_comment.c_str(), &status ); | |||
1108 | } | |||
1109 | } | |||
1110 | ||||
1111 | // If card is history then write history | |||
1112 | else if (m_keyname == "HISTORY") { | |||
1113 | if (m_comment_write) { | |||
1114 | status = __ffphis(FPTR(vptr), (char*)m_comment.c_str(), &status)ffphis(((__fitsfile*)vptr), (char*)m_comment.c_str(), &status ); | |||
1115 | } | |||
1116 | } | |||
1117 | ||||
1118 | // If card is BLANKFIELD (empty keyword) then write empty line | |||
1119 | else if (m_keyname == "") { | |||
1120 | if (m_comment_write) { | |||
1121 | status = __ffprec(FPTR(vptr), "", &status)ffprec(((__fitsfile*)vptr), "", &status); | |||
1122 | } | |||
1123 | } | |||
1124 | ||||
1125 | // If card holds a native data type then write it | |||
1126 | else if (m_value_dtype != NULL__null) { | |||
1127 | switch (m_dtype) { | |||
1128 | case __TLOGICAL14: | |||
1129 | { | |||
1130 | int value = (*((bool*)m_value_dtype)) ? 1 : 0; | |||
1131 | status = __ffukyl(FPTR(vptr), (char*)m_keyname.c_str(), value,ffukyl(((__fitsfile*)vptr), (char*)m_keyname.c_str(), value, ( char*)m_comment.c_str(), &status) | |||
1132 | (char*)m_comment.c_str(), &status)ffukyl(((__fitsfile*)vptr), (char*)m_keyname.c_str(), value, ( char*)m_comment.c_str(), &status); | |||
1133 | } | |||
1134 | break; | |||
1135 | case __TSTRING16: | |||
1136 | status = __ffukys(FPTR(vptr), (char*)m_keyname.c_str(),ffukys(((__fitsfile*)vptr), (char*)m_keyname.c_str(), (char*) ((std::string*)m_value_dtype)->c_str(), (char*)m_comment.c_str (), &status) | |||
1137 | (char*)((std::string*)m_value_dtype)->c_str(),ffukys(((__fitsfile*)vptr), (char*)m_keyname.c_str(), (char*) ((std::string*)m_value_dtype)->c_str(), (char*)m_comment.c_str (), &status) | |||
1138 | (char*)m_comment.c_str(), &status)ffukys(((__fitsfile*)vptr), (char*)m_keyname.c_str(), (char*) ((std::string*)m_value_dtype)->c_str(), (char*)m_comment.c_str (), &status); | |||
1139 | break; | |||
1140 | case __TFLOAT42: | |||
1141 | status = __ffukye(FPTR(vptr), (char*)m_keyname.c_str(),ffukye(((__fitsfile*)vptr), (char*)m_keyname.c_str(), *((float *)m_value_dtype), decimals(), (char*)m_comment.c_str(), & status) | |||
1142 | *((float*)m_value_dtype), decimals(),ffukye(((__fitsfile*)vptr), (char*)m_keyname.c_str(), *((float *)m_value_dtype), decimals(), (char*)m_comment.c_str(), & status) | |||
1143 | (char*)m_comment.c_str(), &status)ffukye(((__fitsfile*)vptr), (char*)m_keyname.c_str(), *((float *)m_value_dtype), decimals(), (char*)m_comment.c_str(), & status); | |||
1144 | break; | |||
1145 | case __TDOUBLE82: | |||
1146 | status = __ffukyd(FPTR(vptr), (char*)m_keyname.c_str(),ffukyd(((__fitsfile*)vptr), (char*)m_keyname.c_str(), *((double *)m_value_dtype), decimals(), (char*)m_comment.c_str(), & status) | |||
1147 | *((double*)m_value_dtype), decimals(),ffukyd(((__fitsfile*)vptr), (char*)m_keyname.c_str(), *((double *)m_value_dtype), decimals(), (char*)m_comment.c_str(), & status) | |||
1148 | (char*)m_comment.c_str(), &status)ffukyd(((__fitsfile*)vptr), (char*)m_keyname.c_str(), *((double *)m_value_dtype), decimals(), (char*)m_comment.c_str(), & status); | |||
1149 | break; | |||
1150 | default: | |||
1151 | status = __ffuky(FPTR(vptr), m_dtype, (char*)m_keyname.c_str(),ffuky(((__fitsfile*)vptr), m_dtype, (char*)m_keyname.c_str(), m_value_dtype, (char*)m_comment.c_str(), &status) | |||
1152 | m_value_dtype, (char*)m_comment.c_str(), &status)ffuky(((__fitsfile*)vptr), m_dtype, (char*)m_keyname.c_str(), m_value_dtype, (char*)m_comment.c_str(), &status); | |||
1153 | break; | |||
1154 | } | |||
1155 | } // endif: had native data type | |||
1156 | ||||
1157 | // ... otherwise if card holds a NULL value then write it | |||
1158 | else if (m_dtype == __TNULL0) { | |||
1159 | status = __ffukyu(FPTR(vptr), (char*)m_keyname.c_str(),ffukyu(((__fitsfile*)vptr), (char*)m_keyname.c_str(), (char*) m_comment.c_str(), &status) | |||
1160 | (char*)m_comment.c_str(), &status)ffukyu(((__fitsfile*)vptr), (char*)m_keyname.c_str(), (char*) m_comment.c_str(), &status); | |||
1161 | } | |||
1162 | ||||
1163 | // ... capture all other stuff | |||
1164 | else { | |||
1165 | std::string msg = "The code should never arrive at this point!\n" | |||
1166 | "The keyname \""+m_keyname+"\" is neither" | |||
1167 | " \"COMMENT\" nor \"HISTRORY\" but it has a" | |||
1168 | " NULL data type value and a data type of" | |||
1169 | " "+gammalib::str(m_dtype)+".\n" | |||
1170 | "Maybe an invalid FITS header card has been" | |||
1171 | " encountered in reading a file?"; | |||
1172 | gammalib::warning(G_WRITE"GFitsHeaderCard::write(void*)", msg); | |||
1173 | } | |||
1174 | ||||
1175 | // Throw exception in case of a FITS error | |||
1176 | if (status != 0) { | |||
1177 | throw GException::fits_error(G_WRITE"GFitsHeaderCard::write(void*)", status); | |||
1178 | } | |||
1179 | ||||
1180 | // Return | |||
1181 | return; | |||
1182 | } |