00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 #include "drms.h"
00120 #include "dr.h"
00121
00122
00123
00124
00125
00126 double dr_A_Signaling_dNaN () {
00127 dNaN x;
00128 x.NaN_mask.sign = 0;
00129 x.NaN_mask.exp = ~0;
00130 x.NaN_mask.quiet = 0;
00131 x.NaN_mask.frac = ~0;
00132 x.NaN_mask.frac1 = 0;
00133 x.NaN_mask.frac2 = 0;
00134 return (x.d);
00135 }
00136
00137 double dr_A_Quiet_dNaN () {
00138 dNaN x;
00139 x.NaN_mask.sign = 0;
00140 x.NaN_mask.exp = ~0;
00141 x.NaN_mask.quiet = ~0;
00142 x.NaN_mask.frac = ~0;
00143 x.NaN_mask.frac1 = 0;
00144 x.NaN_mask.frac2 = 0;
00145 return (x.d);
00146 }
00147
00148 float dr_A_Signaling_fNaN () {
00149 fNaN x;
00150 x.NaN_mask.sign = 0;
00151 x.NaN_mask.exp = ~0;
00152 x.NaN_mask.quiet = 0;
00153 x.NaN_mask.frac = ~0;
00154 x.NaN_mask.frac1 = 0;
00155 return (x.f);
00156 }
00157
00158 float dr_A_Quiet_fNaN () {
00159 fNaN x;
00160 x.NaN_mask.sign = 0;
00161 x.NaN_mask.exp = ~0;
00162 x.NaN_mask.quiet = ~0;
00163 x.NaN_mask.frac = ~0;
00164 x.NaN_mask.frac1 = 0;
00165 return (x.f);
00166 }
00167
00168 double dr_dInfinity () {
00169 dNaN x;
00170 x.NaN_mask.sign = 0;
00171 x.NaN_mask.exp = ~0;
00172 x.NaN_mask.quiet = 0;
00173 x.NaN_mask.frac = 0;
00174 x.NaN_mask.frac1 = 0;
00175 x.NaN_mask.frac2 = 0;
00176 return (x.d);
00177 }
00178
00179 float dr_fInfinity () {
00180 fNaN x;
00181 x.NaN_mask.sign = 0;
00182 x.NaN_mask.exp = ~0;
00183 x.NaN_mask.quiet = 0;
00184 x.NaN_mask.frac = 0;
00185 x.NaN_mask.frac1 = 0;
00186 return (x.f);
00187 }
00188
00189
00190
00191
00192
00193
00194
00195 #ifdef TIMEREP
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 #include <string.h>
00257 #include <stdio.h>
00258
00259 static struct date_time {
00260 double second;
00261 double julday;
00262 double delta;
00263 int year;
00264 int month;
00265 int dofm;
00266 int dofy;
00267 int hour;
00268 int minute;
00269 int civil;
00270 int ut_flag;
00271 char zone[8];
00272 } dattim;
00273
00274 static int molen[] = {31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
00275
00276 static double ut_leap_time[] = {
00277
00278
00279
00280
00281
00282
00283
00284 -536543999.0,
00285 -457747198.0,
00286 -394588797.0,
00287 -363052796.0,
00288 -331516795.0,
00289 -284083194.0,
00290 -252460793.0,
00291 -220924792.0,
00292 -189388791.0,
00293 -157852790.0,
00294 -142127989.0,
00295 -126230388.0,
00296 -94694387.0,
00297 -63158386.0,
00298 -31622385.0,
00299 16.0,
00300 31536017.0,
00301 63072018.0,
00302 94608019.0,
00303 141868820.0,
00304 173404821.0,
00305 204940822.0,
00306 268099223.0,
00307 347068824.0,
00308 410227225.0,
00309 441763226.0,
00310 489024027.0,
00311 520560028.0,
00312 552096029.0,
00313 599529630.0,
00314 646790431.0,
00315 694224032.0,
00316 915148833.0
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 };
00342
00343 static void date_from_epoch_time (TIME t);
00344 static TIME epoch_time_from_date ();
00345 static TIME epoch_time_from_julianday ();
00346
00347 static void _clear_date_time () {
00348
00349
00350
00351 dattim.julday = 0.0;
00352 strcpy (dattim.zone, "TAI");
00353 date_from_epoch_time (epoch_time_from_julianday ());
00354 }
00355
00356 static int _parse_error () {
00357 _clear_date_time ();
00358 return -1;
00359 }
00360
00361 static void _fracday_2_clock (double fdofm) {
00362
00363
00364
00365 dattim.dofm = fdofm;
00366 dattim.second = 86400.0 * (fdofm - dattim.dofm);
00367 dattim.hour = dattim.second / 3600.0;
00368 dattim.second -= 3600.0 * dattim.hour;
00369 dattim.minute = dattim.second / 60.0;
00370 dattim.second -= 60.0 * dattim.minute;
00371 dattim.ut_flag = 0;
00372 }
00373
00374 static int _parse_clock (char *str) {
00375
00376
00377
00378 int status;
00379 char *field0, *field1, *field2;
00380
00381 field0 = strtok (str, ":");
00382 status = sscanf (field0, "%d", &dattim.hour);
00383 if (status != 1) return _parse_error ();
00384 field1 = strtok (NULL, ":");
00385 if (!field1) return _parse_error ();
00386 status = sscanf (field1, "%d", &dattim.minute);
00387 if (status != 1) return _parse_error ();
00388 field2 = strtok (NULL, ":");
00389 if (!field2) {
00390
00391 dattim.second = 0.0;
00392 return (2);
00393 }
00394 status = sscanf (field2, "%lf", &dattim.second);
00395 if (status != 1) return _parse_error ();
00396
00397 dattim.ut_flag = (dattim.second >= 60.0);
00398 return (3);
00399 }
00400
00401 static int _parse_month_name (char *moname) {
00402 int month;
00403
00404 if (!strncmp (moname, "JAN", 3) || !strcmp (moname, "I"))
00405 month = 1;
00406 else if (!strncmp (moname, "FEB", 3) || !strcmp (moname, "II"))
00407 month = 2;
00408 else if (!strncmp (moname, "MAR", 3) || !strcmp (moname, "III"))
00409 month = 3;
00410 else if (!strncmp (moname, "APR", 3) || !strcmp (moname, "IV"))
00411 month = 4;
00412 else if (!strncmp (moname, "MAY", 3) || !strcmp (moname, "V"))
00413 month = 5;
00414 else if (!strncmp (moname, "JUN", 3) || !strcmp (moname, "VI"))
00415 month = 6;
00416 else if (!strncmp (moname, "JUL", 3) || !strcmp (moname, "VII"))
00417 month = 7;
00418 else if (!strncmp (moname, "AUG", 3) || !strcmp (moname, "VIII"))
00419 month = 8;
00420 else if (!strncmp (moname, "SEP", 3) || !strcmp (moname, "IX"))
00421 month = 9;
00422 else if (!strncmp (moname, "OCT", 3) || !strcmp (moname, "X"))
00423 month = 10;
00424 else if (!strncmp (moname, "NOV", 3) || !strcmp (moname, "XI"))
00425 month = 11;
00426 else if (!strncmp (moname, "DEC", 3) || !strcmp (moname, "XII"))
00427 month = 12;
00428 else
00429
00430 month = 0;
00431 return (month);
00432 }
00433
00434 static int _parse_date (char *str) {
00435
00436
00437
00438 double fracday;
00439 int status, dfrac;
00440 char *field0, *field1, *field2, *field3;
00441 char daystr[32];
00442
00443 field0 = strtok (str, ".");
00444 field1 = strtok (NULL, ".");
00445 field2 = strtok (NULL, ".");
00446 field3 = strtok (NULL, ".");
00447 status = sscanf (field0, "%d", &dattim.year);
00448 if (status != 1) return _parse_error ();
00449 if (strlen (field0) == 2) {
00450
00451 if (dattim.year < 10) dattim.year += 100;
00452 dattim.year += 1900;
00453 }
00454 if (!field1) return _parse_error ();
00455 status = sscanf (field1, "%d", &dattim.month);
00456 if (status != 1) {
00457 dattim.month = _parse_month_name (field1);
00458 if (dattim.month == 0) return _parse_error ();
00459 }
00460 if (!field1) return _parse_error ();
00461 status = sscanf (field2, "%d", &dattim.dofm);
00462 if (status != 1) return _parse_error ();
00463 if (field3) {
00464 status = sscanf (field3, "%d", &dfrac);
00465 if (status) {
00466
00467 sprintf (daystr, "%d.%d", dattim.dofm, dfrac);
00468 sscanf (daystr, "%lf", &fracday);
00469 _fracday_2_clock (fracday);
00470 status = 6;
00471 }
00472 }
00473 else status = 3;
00474 return status;
00475 }
00476
00477 static void _raise_case (char *s) {
00478
00479
00480
00481 while (*s) {
00482 if (*s >= 'a' && *s <= 'z')
00483 *s += 'A' - 'a';
00484 s++;
00485 }
00486 }
00487
00488 static int _parse_date_time (char *str) {
00489
00490
00491
00492
00493
00494
00495
00496 double fdofm;
00497 int status;
00498 int length;
00499 char *field0, *field1, *field2;
00500
00501 _raise_case (str);
00502 length = strlen (str);
00503 if (!length) return _parse_error ();
00504 field0 = strtok (str, "_");
00505 if ((strlen (field0)) == length) {
00506
00507
00508 status = sscanf (str, "%d.%d.%lf", &dattim.year, &dattim.month, &fdofm);
00509 if (status != 3) return _parse_error ();
00510 _fracday_2_clock (fdofm);
00511 strcpy (dattim.zone, "UTC");
00512 return 0;
00513 }
00514
00515 field1 = strtok (NULL, "_");
00516 if (!(strcmp (field0, "MJD")) || !(strcmp (field0, "JD"))) {
00517 status = sscanf (field1, "%lf", &dattim.julday);
00518 if (status != 1) return _parse_error ();
00519 field2 = strtok (NULL, "_");
00520 if (field2)
00521 strcpy (dattim.zone, field2);
00522 else
00523
00524 strcpy (dattim.zone, "TDT");
00525 if (field0[0] == 'M')
00526
00527 dattim.julday += 2400000.5;
00528 return 1;
00529 }
00530
00531 dattim.julday = 0.0;
00532 field2 = strtok (NULL, "_");
00533 status = _parse_date (field0);
00534 if (status == 3) {
00535 status = _parse_clock (field1);
00536 if (!status) return _parse_error ();
00537 }
00538 else if (status == 6)
00539 field2 = field1;
00540 if (field2)
00541 strcpy (dattim.zone, field2);
00542 else
00543
00544 strcpy (dattim.zone, "UTC");
00545 return 0;
00546 }
00547
00548 #define JD_EPOCH (2443144.5)
00549 #define EPOCH_2000_01_01 ( 725760000.0)
00550 #define EPOCH_1601_01_01 (-11865398400.0)
00551 #define EPOCH_1600_01_01 (-11897020800.0)
00552 #define EPOCH_1582_10_15 (-12440217600.0)
00553 #define EPOCH_1581_01_01 (-12495686400.0)
00554 #define SEC_DAY (86400.0)
00555 #define SEC_YEAR (31536000.0)
00556 #define SEC_BSYR (31622400.0)
00557 #define SEC_YEAR4 (126144000.0)
00558 #define SEC_4YRS (126230400.0)
00559 #define SEC_GCNT (3155673600.0)
00560 #define SEC_JCNT (3155760000.0)
00561 #define SEC_GR4C (12622780800.0)
00562 #define SEC_JL4C (12623040000.0)
00563
00564 static void date_from_epoch_time (TIME t) {
00565 double century, four_year, one_year;
00566 int year, month, day;
00567
00568 if (t < EPOCH_1582_10_15) {
00569
00570 year = 1585;
00571 t -= EPOCH_1581_01_01 + SEC_4YRS;
00572 while (t < -SEC_JL4C) {
00573 t += SEC_JL4C;
00574 year -= 400;
00575 }
00576 while (t < -SEC_JCNT) {
00577 t += SEC_JCNT;
00578 year -= 100;
00579 }
00580 while (t < -SEC_4YRS) {
00581 t += SEC_4YRS;
00582 year -= 4;
00583 }
00584 one_year = SEC_BSYR;
00585 while (t < 0.0) {
00586 t += one_year;
00587 year -= 1;
00588 one_year = SEC_YEAR;
00589 }
00590 }
00591 else {
00592 year = 1600;
00593 t -= EPOCH_1600_01_01;
00594 while (t < -SEC_4YRS) {
00595 t += SEC_4YRS;
00596 year -= 4;
00597 }
00598 one_year = SEC_YEAR;
00599 while (t < 0.0) {
00600 t += one_year;
00601 year -= 1;
00602 one_year = (year % 4 == 1) ? SEC_BSYR : SEC_YEAR;
00603 }
00604 }
00605
00606 century = SEC_JCNT;
00607 while (t >= century) {
00608 t -= century;
00609 year += 100;
00610 century = (year % 400) ? SEC_GCNT : SEC_JCNT;
00611 }
00612 four_year = (year % 100) ? SEC_4YRS : (year % 400) ? SEC_YEAR4 : SEC_4YRS;
00613 while (t >= four_year) {
00614 t -= four_year;
00615 year += 4;
00616 four_year = SEC_4YRS;
00617 }
00618 one_year = (year % 4) ? SEC_YEAR : (year % 100) ? SEC_BSYR : (year % 400) ?
00619 SEC_YEAR : SEC_BSYR;
00620 while (t >= one_year) {
00621 t -= one_year;
00622 year += 1;
00623 one_year = SEC_YEAR;
00624 }
00625
00626 dattim.year = year;
00627 if (year%4 == 0)
00628 molen[2] = 29;
00629 if ((year%100 == 0) && (year > 1600) && (year%400 != 0))
00630 molen[2] = 28;
00631 month = 1;
00632 day = t / SEC_DAY;
00633 while (day >= molen[month]) {
00634 day -= molen[month];
00635 t -= SEC_DAY * molen[month];
00636 month++;
00637 }
00638 molen[2] = 28;
00639 dattim.month = month;
00640 dattim.dofm = t / SEC_DAY;
00641 t -= SEC_DAY * dattim.dofm;
00642 dattim.dofm++;
00643 dattim.hour = t / 3600.0;
00644 t -= 3600.0 * dattim.hour;
00645 dattim.minute = t / 60.0;
00646 t -= 60.0 * dattim.minute;
00647 dattim.second = t;
00648 }
00649
00650 static TIME epoch_time_from_date () {
00651 TIME t;
00652 int mon, yr1601;
00653
00654 t = dattim.second + 60.0 * (dattim.minute + 60.0 * (dattim.hour));
00655 t += SEC_DAY * (dattim.dofm - 1);
00656 while (dattim.month < 1) {
00657 dattim.year--;
00658 dattim.month += 12;
00659 }
00660 while (dattim.month > 12) {
00661 dattim.year++;
00662 dattim.month -= 12;
00663 }
00664 yr1601 = dattim.year - 1601;
00665 if (yr1601 < 0) {
00666 if (dattim.year%4 ==0)
00667 molen[2] = 29;
00668 while (yr1601 < 1) {
00669 t -= SEC_JL4C;
00670 yr1601 += 400;
00671 }
00672 while (yr1601 > 99) {
00673 t += SEC_JCNT;
00674 yr1601 -= 100;
00675 }
00676 }
00677 else {
00678 if (dattim.year%400 == 0 || (dattim.year%4 == 0 && dattim.year%100 != 0))
00679 molen[2] = 29;
00680 while (yr1601 > 399) {
00681 t += SEC_GR4C;
00682 yr1601 -= 400;
00683 }
00684 while (yr1601 > 99) {
00685 t += SEC_GCNT;
00686 yr1601 -= 100;
00687 }
00688 }
00689 for (mon=1; mon<dattim.month; mon++) {
00690 t += SEC_DAY * molen[mon];
00691 }
00692 molen[2] = 28;
00693 while (yr1601 > 3) {
00694 t += SEC_4YRS;
00695 yr1601 -= 4;
00696 }
00697 while (yr1601 > 0) {
00698 t += SEC_YEAR;
00699 yr1601 -= 1;
00700 }
00701 t += EPOCH_1601_01_01;
00702 if (t < EPOCH_1582_10_15)
00703
00704 t += 10 * SEC_DAY;
00705 return (t);
00706 }
00707
00708 static TIME epoch_time_from_julianday () {
00709 TIME t;
00710
00711 t = SEC_DAY * (dattim.julday - JD_EPOCH);
00712 return (t);
00713 }
00714
00715 static TIME zone_adjustment (char *zone) {
00716 TIME dt;
00717 int status, offset, hours, minutes;
00718
00719 dt = 0.0;
00720 hours = minutes = 0;
00721 status = sscanf (zone, "%5d", &offset);
00722 if (status) {
00723 hours = offset / 100;
00724 minutes = offset % 100;
00725 dt += 60.0 * (minutes + 60.0 * hours);
00726 return dt;
00727 }
00728 if (strlen (zone) == 1) {
00729 hours = zone[0] - 'A' + 1;
00730 if (zone[0] > 'I')
00731 hours--;
00732 if (zone[0] > 'M') {
00733 hours = 'M' - zone[0];
00734 if (zone[0] == 'Z')
00735 hours = 0;
00736 }
00737 dt += 3600.0 * hours;
00738 return dt;
00739 }
00740 if (!strcmp (zone, "PST") || !strcmp (zone, "YDT"))
00741 hours = -8;
00742 else if (!strcmp (zone, "MST") || !strcmp (zone, "PDT"))
00743 hours = -7;
00744 else if (!strcmp (zone, "CST") || !strcmp (zone, "MDT"))
00745 hours = -6;
00746 else if (!strcmp (zone, "EST") || !strcmp (zone, "CDT"))
00747 hours = -5;
00748 else if (!strcmp (zone, "AST") || !strcmp (zone, "EDT"))
00749 hours = -4;
00750 else if (!strcmp (zone, "ADT"))
00751 hours = -3;
00752 else if (!strcmp (zone, "GMT") || !strcmp (zone, "WET"))
00753 hours = 0;
00754 else if (!strcmp (zone, "CET") || !strcmp (zone, "BST"))
00755 hours = 1;
00756 else if (!strcmp (zone, "EET"))
00757 hours = 2;
00758 else if (!strcmp (zone, "SST") || !strcmp (zone, "WST"))
00759 hours = 8;
00760 else if (!strcmp (zone, "JST"))
00761 hours = 9;
00762 else if (!strcmp (zone, "JDT"))
00763 hours = 10;
00764 else if (!strcmp (zone, "NZST"))
00765 hours = 12;
00766 else if (!strcmp (zone, "BST"))
00767 hours = -11;
00768 else if (!strcmp (zone, "HST") || !strcmp (zone, "BDT"))
00769 hours = -10;
00770 else if (!strcmp (zone, "YST") || !strcmp (zone, "HDT"))
00771 hours = -9;
00772 else if (!strcmp (zone, "NZDT"))
00773 hours = 13;
00774 dt += 3600.0 * hours;
00775 return dt;
00776 }
00777
00778 TIME _tai_adjustment (TIME t, char *zone) {
00779 TIME dt;
00780 int leapsecs, ct;
00781
00782 _raise_case (zone);
00783 if (!strcmp (zone, "TAI")) {
00784 dattim.civil = 0;
00785 return 0.0;
00786 }
00787 if (!strcmp (zone, "TDT") || !strcmp (zone, "TT")) {
00788 dattim.civil = 0;
00789 return 32.184;
00790 }
00791 if (!strcmp (zone, "GPS")) {
00792 dattim.civil = 0;
00793 return -19.0;
00794 }
00795
00796 dattim.civil = 1;
00797 leapsecs = sizeof (ut_leap_time) / sizeof (TIME);
00798 dt = 0.0;
00799 if (t >= ut_leap_time[0]) {
00800 t += 1.0;
00801 for (ct=0; ct<leapsecs && t>=ut_leap_time[ct]; ct++) {
00802 t += 1.0;
00803 dt -= 1.0;
00804 }
00805 if (dattim.ut_flag) dt += 1.0;
00806 }
00807 return (dt + zone_adjustment (zone));
00808 }
00809
00810 TIME _utc_adjustment (TIME t, char *zone) {
00811 TIME dt;
00812 int leapsecs, ct;
00813
00814 dattim.ut_flag = 0;
00815 _raise_case (zone);
00816 if (!strcmp (zone, "TAI")) {
00817 dattim.civil = 0;
00818 return 0.0;
00819 }
00820 if (!strcmp (zone, "TDT") || !strcmp (zone, "TT")) {
00821 dattim.civil = 0;
00822 return 32.184;
00823 }
00824 if (!strcmp (zone, "GPS")) {
00825 dattim.civil = 0;
00826 return -19.0;
00827 }
00828
00829 dattim.civil = 1;
00830 leapsecs = sizeof (ut_leap_time) / sizeof (TIME);
00831 dt = 0.0;
00832 for (ct=0; ct<leapsecs; ct++) {
00833 if (t < (ut_leap_time[ct] - 1.0))
00834 break;
00835 dt -= 1.0;
00836 if (t < ut_leap_time[ct])
00837 dattim.ut_flag = 1;
00838
00839
00840
00841
00842 }
00843 return (dt + zone_adjustment (zone));
00844 }
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861 void _sprint_time (char *out, TIME t, char *zone, int precision) {
00862 char format[64];
00863
00864 t += utc_adjustment (t, zone);
00865 date_from_epoch_time (t);
00866 if (dattim.ut_flag) {
00867 dattim.second += 1.0;
00868 }
00869 if (precision > 0) {
00870 sprintf (format, "%s%02d.%df_%%s", "%04d.%02d.%02d_%02d:%02d:%",
00871 precision+3, precision);
00872 sprintf (out, format, dattim.year, dattim.month, dattim.dofm,
00873 dattim.hour, dattim.minute, dattim.second, zone);
00874 } else if (precision == 0)
00875 sprintf (out, "%04d.%02d.%02d_%02d:%02d:%02.0f_%s",
00876 dattim.year, dattim.month, dattim.dofm,
00877 dattim.hour, dattim.minute, dattim.second, zone);
00878 else {
00879 while (dattim.second >= 30.0) {
00880 dattim.minute++;
00881 dattim.second -= 60.0;
00882 if (dattim.minute == 60) {
00883 dattim.minute = 0;
00884 dattim.hour++;
00885 if (dattim.hour == 24) {
00886 dattim.hour = 0;
00887 dattim.dofm++;
00888 if (dattim.dofm > molen[dattim.month]) {
00889 if (dattim.month == 2) {
00890 if ((dattim.year < 1601) && ((dattim.year % 4) == 0)) break;
00891 if (((dattim.year % 4) == 0) && (dattim.year % 100)) break;
00892 if ((dattim.year % 400) == 0) break;
00893 } else {
00894 dattim.dofm = 1;
00895 dattim.month++;
00896 if (dattim.month == 13) {
00897 dattim.month = 1;
00898 dattim.year++;
00899 }
00900 }
00901 }
00902 }
00903 }
00904 }
00905 sprintf (out, "%04d.%02d.%02d_%02d:%02d_%s",
00906 dattim.year, dattim.month, dattim.dofm,
00907 dattim.hour, dattim.minute, zone);
00908 }
00909 }
00910
00911 #endif
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921 static _llist *dr_LastElement (_llist **l) {
00922 _llist *result, *ll = *l;
00923
00924 if (ll == NULL) return NULL;
00925 while (ll) {
00926 result = ll;
00927 ll = ll->next;
00928 }
00929 return result;
00930 }
00931
00932 static _llist *dr_insert (_llist *ll, _llist* new) {
00933 _llist *temp;
00934
00935 if ((ll == NULL) || (new == NULL)) return NULL;
00936 temp = dr_LastElement (&new);
00937 temp->next = ll->next;
00938 ll->next = new;
00939 return new;
00940 }
00941
00942 void dr_AddList (_llist **l, _llist *new) {
00943 _llist *ll = *l;
00944 if (new == NULL) return;
00945 if (ll == NULL) {
00946 *l = new;
00947 (*l)->next = NULL;
00948 } else dr_insert (dr_LastElement (l), new);
00949 }
00950
00951 static _llist *dr_GetNthElement (_llist **l, int n) {
00952 int count = 0;
00953 _llist *ll = *l;
00954
00955 while (ll) {
00956 count++;
00957 if (count == n) return ll;
00958 ll = ll->next;
00959 }
00960 return NULL;
00961 }
00962
00963 _llist *dr_RemoveNthElement (_llist **l, int n) {
00964 _llist *result, *ll = *l;
00965
00966 if (ll == NULL) return NULL;
00967 if (n == 1) {
00968 result = ll;
00969 *l = ll->next;
00970 return (result);
00971 }
00972 ll = dr_GetNthElement (l, n-1);
00973 if (ll && ll->next) {
00974 result = ll->next;
00975 ll->next = ll->next->next;
00976 return (result);
00977 }
00978 else return NULL;
00979 }
00980
00981 _llist *dr_MapList (_llist **l, _llistFn fn, void *obj) {
00982 _llist *hold, *ll = *l;
00983
00984 while (ll) {
00985 hold = ll->next;
00986 if ((*fn)(ll, obj)) break;
00987 ll = hold;
00988 }
00989 return ll;
00990 }
00991
00992
00993
00994
00995
00996 #include <string.h>
00997
00998
00999 static int dr_search_attr_mapfn (ATTRIBUTES *attr, char *key)
01000 {
01001 if (attr->name == NULL) return 0;
01002 return (strcmp (attr->name, key) == 0);
01003 }
01004
01005 char *dr_attrname (ATTRIBUTES *attr)
01006 {
01007 return (attr) ? (attr->name) : (char *)attr;
01008 }
01009
01010 void *dr_attrvalue (ATTRIBUTES *attr)
01011 {
01012 return (attr) ? (attr->value) : attr;
01013 }
01014
01015 char *dr_attrvalue_str (ATTRIBUTES *attr)
01016 {
01017 char *str = NULL;
01018 static char line[DR_MAXSTRING+1];
01019
01020 if (dr_attrvalue (attr) == NULL) return NULL;
01021 line[0] = '\0';
01022
01023 switch(attr->datatype)
01024 {
01025 case DR_LOGICAL:
01026 sprintf (line, "%c", *(char *)attr->value);
01027 break;
01028 case DR_BYTE:
01029 sprintf (line, "%d", *(signed char *)attr->value);
01030 break;
01031 case DR_SHORT:
01032 sprintf (line, "%d", *(short*)attr->value);
01033 break;
01034 case DR_INT:
01035 sprintf (line, "%d", *(int*)attr->value);
01036 break;
01037 case DR_LONG:
01038
01039 sprintf (line, "%ld", *(long *)attr->value);
01040 break;
01041 case DR_FLOAT:
01042 sprintf (line, "%0.8E", *(float *)attr->value);
01043 break;
01044 case DR_DOUBLE:
01045
01046 sprintf (line, "%0.12E", *(double *)attr->value);
01047 break;
01048 case DR_TIME:
01049 sprint_time (line, *(double *)attr->value, "UT", 0);
01050 break;
01051 case DR_STRING:
01052 sprintf (line, "%0.*s", DR_MAXSTRING, (char *)attr->value);
01053 break;
01054 case DR_VOID:
01055 return NULL;
01056 case DR_COMPLEX:
01057
01058 return NULL;
01059 default:
01060
01061 return NULL;
01062 }
01063 str = strdup (line);
01064 return str;
01065 }
01066
01067 ATTRIBUTES *dr_next_attr (ATTRIBUTES *attr)
01068 {
01069 if (attr == NULL) return (NULL);
01070 else return (attr->next);
01071 }
01072
01073 ATTRIBUTES *dr_search_attr (DR *dr, char *key)
01074 {
01075 ATTRIBUTES *attr;
01076 if (!dr) return NULL;
01077 if (!key) return NULL;
01078 if (!(attr = (ATTRIBUTES *)dr_MapList ((_llist **) &(dr->attrib),
01079 (_llistFn) dr_search_attr_mapfn, (void *) key)))
01080 return NULL;
01081 return (attr);
01082 }
01083
01084
01085 int dr_attrtype(ATTRIBUTES *attr)
01086 {
01087 if (attr==NULL)
01088 {
01089 return 0;
01090 }
01091 return ((int)attr->datatype);
01092 }
01093
01094
01095 int dr_attribute_type (DR *drptr, char *key)
01096 {
01097 ATTRIBUTES *attrptr;
01098 int datatype;
01099
01100 attrptr = dr_search_attr (drptr, key);
01101 datatype = dr_attrtype (attrptr);
01102 return (datatype);
01103 }
01104
01105
01106
01107
01108
01109 void *dr_search_attrvalue (DR *dr, char *key)
01110 {
01111 ATTRIBUTES *attr;
01112 attr = dr_search_attr (dr, key);
01113 return (dr_attrvalue (attr));
01114 }
01115
01116
01117
01118
01119
01120 char *dr_search_attrvalue_str (DR *dr, char *key)
01121 {
01122 ATTRIBUTES *attr;
01123 attr = dr_search_attr (dr, key);
01124 return (dr_attrvalue_str (attr));
01125 }
01126
01127
01128
01129
01130
01131
01132
01133 double dr_search_attrvalue_double (DR *dr, char *key)
01134 {
01135 ATTRIBUTES *attr;
01136 double dnum;
01137 char *endptr[1];
01138
01139 attr = dr_search_attr (dr, key);
01140 if (attr)
01141 {
01142 switch(attr->datatype)
01143 {
01144 case DR_BYTE:
01145 dnum = *(signed char *)attr->value;
01146 break;
01147 case DR_SHORT:
01148 dnum = (double) *(short *)attr->value;
01149 break;
01150 case DR_INT:
01151 dnum = (double) *(int *)attr->value;
01152 break;
01153 case DR_LONG:
01154 dnum = (double) *(long *)attr->value;
01155 break;
01156 case DR_FLOAT:
01157 dnum = (double) *(float *)attr->value;
01158 break;
01159 case DR_DOUBLE:
01160 case DR_TIME:
01161 dnum = *(double *)(attr->value);
01162 break;
01163 case DR_STRING:
01164 dnum = strtod (attr->value, endptr);
01165 if (attr->value == *endptr)
01166 {
01167 return (D_MISSING);
01168 }
01169 if (**endptr != '\0')
01170 {
01171 return (D_MISSING);
01172 }
01173 break;
01174 case DR_COMPLEX:
01175 case DR_VOID:
01176 default:
01177 return (D_MISSING);
01178 }
01179 return (dnum);
01180 }
01181 else
01182 return (D_MISSING);
01183 }
01184
01185
01186
01187
01188
01189
01190 double dr_bscale (DR *dr)
01191 {
01192 return (dr) ? dr->bscale : dr_A_Signaling_dNaN ();
01193 }
01194
01195 double dr_bzero (DR *dr)
01196 {
01197 return (dr) ? dr->bzero : dr_A_Signaling_dNaN ();
01198 }
01199
01200 void *dr_data (DR *dr)
01201 {
01202 return (dr) ? dr->data : NULL;
01203 }
01204
01205 int dr_datatype (DR *dr)
01206 {
01207 return (dr) ? (int)dr->datatype : -1;
01208 }
01209
01210 int dr_numbytes (DR *dr)
01211 {
01212 return (dr) ? (int)dr->datumsize : -1;
01213 }
01214
01215 int dr_rank (DR *dr)
01216 {
01217 return (dr) ? dr->rank : -1;
01218 }
01219
01220 int *dr_length (DR *dr)
01221 {
01222 return (dr) ? dr->length : NULL;
01223 }
01224
01225 int dr_dim_n (DR *dr, int n)
01226 {
01227 int rank, *length;
01228
01229 if ((rank = dr_rank (dr)) < 0) return -1;
01230
01231 if (n < 0 || n > rank) return -1;
01232 if (rank == 0) return 0;
01233
01234 if (!(length = dr_length (dr))) return -1;
01235 return length[n];
01236 }
01237
01238 long dr_data_length (DR *dr)
01239 {
01240 int rank, i;
01241 long dlength = 1;
01242
01243 if ((rank = dr_rank (dr)) < 0) return -1;
01244 if (rank == 0 || dr->length == NULL) return 0;
01245
01246 for (i=0; i<rank; i++)
01247 dlength *= dr->length[i];
01248 return dlength;
01249 }
01250
01251 int dr_sizeof (int datatype)
01252 {
01253 switch (datatype)
01254 {
01255 case DR_VOID:
01256 return 0;
01257 case DR_BYTE:
01258 case DR_LOGICAL:
01259 return sizeof (char);
01260 case DR_SHORT:
01261 return sizeof (short);
01262 case DR_INT:
01263 return sizeof (int);
01264 case DR_LONG:
01265 return sizeof (long);
01266 case DR_FLOAT:
01267 return sizeof (float);
01268 case DR_DOUBLE:
01269 case DR_TIME:
01270 return sizeof (double);
01271 case DR_COMPLEX:
01272 return 2 * sizeof (float);
01273 case DR_STRING:
01274 return sizeof (char *);
01275 default:
01276 return DR_INVALID_DATATYPE;
01277 }
01278 }
01279
01280
01281
01282
01283
01284 #include <stdlib.h>
01285 static int append_internal_str (char **old, char *new)
01286 {
01287 int length;
01288
01289 if (!new) return NO_ERROR;
01290 if (!old) return ATTR_POINTER_NULL;
01291 if (!*old)
01292 {
01293 *old = (char *)malloc (strlen (new) + 1);
01294 if (!*old) return MALLOC_FAILURE;
01295 strcpy (*old, new);
01296 }
01297 else
01298 {
01299 length = strlen (*old) + strlen (new) + 1;
01300 *old = (char *)realloc (*old, length);
01301 if (!*old) return MALLOC_FAILURE;
01302 strcat (*old, new);
01303 }
01304 return NO_ERROR;
01305 }
01306
01307 int dr_append_comment (DR *dr, char *str)
01308 {
01309 return append_internal_str (&(dr->comment), str);
01310 }
01311
01312 int dr_append_history (DR *dr, char *str)
01313 {
01314 return append_internal_str (&dr->history, str);
01315 }
01316
01317 char *dr_datatypename (DR *dr)
01318 {
01319 static char *name[] = {"Void", "SignedByte", "UnsignedByte", "Short",
01320 "UnsignedShort", "Integer", "UnsignedInteger", "Long", "UnsignedLong",
01321 "Float", "Double", "Complex", "String", "Time",
01322 "Logical", "illegal"};
01323 int datatype = dr_datatype (dr);
01324 int known = sizeof (name) / sizeof (char *);
01325 if (datatype < 0 || datatype >= known) datatype = known - 1;
01326 return (name[datatype]);
01327 }
01328
01329
01330
01331
01332
01333 #include <stdlib.h>
01334
01335 extern int dr_set_data (DR *dr, void *data);
01336
01337 int *dr_malloc_length (int rank)
01338 {
01339 int *length;
01340 if (rank == 0) return NULL;
01341 length = (int *)malloc (rank * sizeof(int));
01342 if (!length) return NULL;
01343 while (rank--) length[rank] = 1;
01344 return length;
01345 }
01346
01347 char *dr_malloc_string (int numchars)
01348 {
01349 char *str;
01350 if (str = (char *)malloc ((1 + numchars) * sizeof(char)))
01351 {
01352 str[numchars] = '\0';
01353 }
01354 return (str);
01355 }
01356
01357 ATTRIBUTES *dr_malloc_attribute (void)
01358 {
01359
01360 ATTRIBUTES *new;
01361
01362 if (!(new = (ATTRIBUTES *) malloc (sizeof (ATTRIBUTES))))
01363 return NULL;
01364 new->next = NULL;
01365 new->name = NULL;
01366 new->value = NULL;
01367 new->format = NULL;
01368 new->comment = NULL;
01369 new->datatype = DR_VOID;
01370
01371 return new;
01372 }
01373
01374 void *dr_malloc_fillvalue (int datatype)
01375 {
01376 int size;
01377 void *fillvalue;
01378
01379 if (!(size = dr_sizeof (datatype))) return NULL;
01380 if (!(fillvalue = malloc (size))) return NULL;
01381 return fillvalue;
01382 }
01383
01384
01385
01386
01387 void *dr_std_fillvalue (int datatype)
01388 {
01389 void *fillvalue;
01390
01391 if (fillvalue = dr_malloc_fillvalue (datatype))
01392 switch (datatype)
01393 {
01394 case DR_BYTE:
01395 *(char *)fillvalue = B_MISSING;
01396 break;
01397 case DR_SHORT:
01398 *(short *)fillvalue = S_MISSING;
01399 break;
01400 case DR_INT:
01401 case DR_LONG:
01402 *(int *)fillvalue = I_MISSING;
01403 break;
01404 case DR_FLOAT:
01405 *(float *)fillvalue = F_MISSING;
01406 break;
01407 case DR_DOUBLE:
01408 *(double *)fillvalue = D_MISSING;
01409 break;
01410 case DR_TIME:
01411 *(double *)fillvalue = T_MISSING;
01412 break;
01413 case DR_COMPLEX:
01414 ((fcomplex *)fillvalue)->r = F_MISSING;
01415 ((fcomplex *)fillvalue)->i = F_MISSING;
01416 break;
01417 case DR_STRING:
01418 *(char**)fillvalue = NULL;
01419 break;
01420 case DR_VOID:
01421 default:
01422 free (fillvalue); fillvalue = NULL;
01423 break;
01424 }
01425 return (fillvalue);
01426 }
01427
01428 static void dr_free_attr (ATTRIBUTES *attr)
01429 {
01430 if (attr == NULL) return;
01431 if (attr->name)
01432 {
01433 free(attr->name);
01434 attr->name = NULL;
01435 }
01436 if (attr->value)
01437 {
01438 free(attr->value);
01439 attr->value = NULL;
01440 }
01441 if (attr->comment)
01442 {
01443 free(attr->comment);
01444 attr->comment = NULL;
01445 }
01446 dr_free_attr (attr->next);
01447 free (attr);
01448 }
01449
01450 static void dr_free_color (DR *dr)
01451 {
01452
01453 int *tmp;
01454 if (!dr) return;
01455 if (!dr->color_table) return;
01456 if (tmp = dr->color_table->Red) free (tmp);
01457 if (tmp = dr->color_table->Blue) free (tmp);
01458 if (tmp = dr->color_table->Green) free (tmp);
01459 dr->color_table = NULL;
01460 }
01461
01462 char *dr_malloc_data (long numbytes)
01463 {
01464 char *str = NULL;
01465 if (numbytes <= 0) return str;
01466 else if (!(str = (char *)malloc ((numbytes)*sizeof(char)))) ;
01467
01468 return (str);
01469 }
01470
01471
01472
01473
01474
01475
01476 int dr_create_data (DR *dr)
01477 {
01478 void *dataptr;
01479 long elements;
01480 int bytes_per_element;
01481
01482 if ((elements = dr_data_length (dr)) < 0) return DR_POINTER_NULL;
01483 bytes_per_element = dr_sizeof (dr->datatype);
01484
01485 dataptr = dr_malloc_data (elements * bytes_per_element);
01486 return dr_set_data (dr, dataptr);
01487 }
01488
01489 DR *dr_create ()
01490 {
01491 DR *new = (DR *)malloc (sizeof (DR));
01492
01493 if (new == NULL) return (new);
01494
01495 new->rank = 0;
01496 new->length = NULL;
01497 new->color_table = NULL;
01498 new->fillval = NULL;
01499 new->data = NULL;
01500 new->data_avail = 0;
01501 new->datatype = DR_VOID;
01502 new->datumsize = 0;
01503 new->attrib = NULL;
01504 new->bscale = 1.0;
01505 new->bzero = 0.0;
01506 new->scaling = 0;
01507 new->comment = new->history = NULL;
01508
01509 return (new);
01510 }
01511
01512 void dr_free_data (DR *dr)
01513 {
01514 if (!dr) return;
01515 if (dr->data) free (dr->data);
01516 dr->data = NULL;
01517 }
01518
01519 static void dr_free_ptrs (DR *dr)
01520 {
01521 if (!dr) return;
01522 dr_free_data (dr);
01523 if (dr->fillval)
01524 {
01525 free (dr->fillval);
01526 dr->fillval = NULL;
01527 }
01528 if (dr->length)
01529 {
01530 free (dr->length);
01531 dr->length = NULL;
01532 }
01533 dr_free_attr (dr->attrib);
01534 dr->attrib = NULL;
01535 if (dr->comment)
01536 {
01537 free (dr->comment);
01538 dr->comment = NULL;
01539 }
01540 if (dr->history)
01541 {
01542 free (dr->history);
01543 dr->history = NULL;
01544 }
01545 dr_free_color (dr);
01546 }
01547
01548 void dr_free (DR **drptr)
01549 {
01550 DR *dr;
01551 if (!drptr || !(dr = *drptr)) return;
01552 dr_free_ptrs (dr);
01553 free (dr);
01554 *drptr = NULL;
01555 }
01556
01557
01558
01559
01560
01561 #include <ctype.h>
01562
01563 char *ConvertToUpper (char *line) {
01564 char *result;
01565 int i;
01566
01567 if (line == NULL) return NULL;
01568 result = (char *) malloc(strlen(line)+1);
01569 for (i=0; line[i] != '\0'; i++) result[i] = toupper(line[i]);
01570 result[i] = '\0';
01571 return result;
01572 }
01573
01574 char *ConvertToLower (char *line) {
01575 char *result;
01576 int i;
01577
01578 if (line == NULL) return NULL;
01579 result = (char *) malloc(strlen(line)+1);
01580 for (i=0; line[i] != '\0'; i++) result[i] = tolower(line[i]);
01581 result[i] = '\0';
01582 return result;
01583 }
01584
01585 static char *FirstNonWhite (char *line)
01586 {
01587 if (line == NULL) return NULL;
01588 while (*line)
01589 {
01590 if (isspace (*line)) line++;
01591 else return line;
01592 }
01593 return NULL;
01594 }
01595
01596 static char *LastNonWhite (char *line)
01597 {
01598 int n;
01599 if (line == NULL) return NULL;
01600
01601 n = strlen (line);
01602 while(n)
01603 {
01604 if (isspace (*(line + n - 1))) n--;
01605 else return (line + n - 1);
01606 }
01607 return NULL;
01608 }
01609
01610
01611
01612
01613
01614
01615 static int numType (char *num)
01616 {
01617 double dval;
01618 long ival;
01619 char c, *ptr, hold;
01620
01621 ptr = LastNonWhite (num);
01622 if (ptr == NULL) return 0;
01623 ptr++;
01624 hold = *ptr;
01625 *ptr = 0;
01626 if (sscanf(num, "%ld%c", &ival, &c) == 1)
01627 {
01628 *ptr = hold;
01629 return 2;
01630 }
01631 #ifdef __linux__
01632 if (num[0] == '0' && (num[1] == 'x' || num[1] == 'X'))
01633 {
01634 *ptr = hold;
01635 return 0;
01636 }
01637 #endif
01638 if (sscanf (num, "%lf%c", &dval, &c) == 1)
01639 {
01640 *ptr = hold;
01641 return 1;
01642 }
01643 *ptr = hold;
01644 return 0;
01645 }
01646
01647 static int header_value_type (char *str)
01648 {
01649 int datatype;
01650
01651 switch (numType (str))
01652 {
01653 case 1:
01654 datatype = DR_DOUBLE;
01655 break;
01656 case 2:
01657 datatype = DR_LONG;
01658 break;
01659 default:
01660 if ((strlen(str)==1)&& ((str[0] == 'T') || (str[0] == 'F')))
01661 datatype = DR_LOGICAL;
01662 else if (str[0] == '/')
01663 datatype = DR_VOID;
01664 else
01665 datatype = DR_STRING;
01666 }
01667 return (datatype);
01668 }
01669
01670
01671
01672
01673
01674 int dr_set_attrvalue (ATTRIBUTES *attr, void *value, int datatype)
01675 {
01676 void *newvalue;
01677 int i, nbytes;
01678
01679 if (!attr) return ATTR_POINTER_NULL;
01680 if (!value && (datatype != DR_VOID)) return ATTRVALUE_NULL;
01681
01682 if (datatype == DR_STRING) nbytes = strlen ((char *)value)+1;
01683 else nbytes = dr_sizeof (datatype);
01684
01685 attr->datatype = datatype;
01686 if (attr->value) free (attr->value);
01687 attr->value = NULL;
01688
01689 if (nbytes)
01690 {
01691 if (!(newvalue = calloc (1, nbytes)))
01692 return MALLOC_FAILURE;
01693
01694 for (i=0; i<nbytes; i++)
01695 *((char*)newvalue + i) = *((char*)value + i);
01696
01697 if (datatype == DR_LOGICAL)
01698 if (*(char *)newvalue == '\000') *(char*)newvalue = 'F';
01699 else if (*(char *)newvalue == '\001') *(char*)newvalue = 'T';
01700
01701 attr->value = newvalue;
01702 }
01703
01704 return NO_ERROR;
01705 }
01706
01707 int dr_set_attrname (ATTRIBUTES *attr, char *name)
01708 {
01709 if (attr == NULL) return ATTR_POINTER_NULL;
01710 if (name == NULL) return ATTRNAME_NULL;
01711 if(attr->name) free(attr->name);
01712 attr->name = NULL;
01713 if (!(attr->name = dr_malloc_string (strlen (name) + 1)))
01714 return MALLOC_FAILURE;
01715 strcpy (attr->name, name);
01716 return NO_ERROR;
01717 }
01718
01719 int dr_set_comment (ATTRIBUTES *attr, char *comment)
01720 {
01721 if (attr == NULL) return ATTR_POINTER_NULL;
01722 if (attr->comment) free (attr->comment);
01723 attr->comment = NULL;
01724 if (comment && (strlen (comment) > 0))
01725 if (!(attr->comment = dr_malloc_string (strlen (comment))))
01726 {
01727 return MALLOC_FAILURE;
01728 }
01729 else
01730 {
01731 strcpy (attr->comment, comment);
01732 }
01733 return NO_ERROR;
01734 }
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745 int dr_set_attribute (DR *dr, char *key, void *value, int attrtype, char *comment)
01746 {
01747 ATTRIBUTES *newattr = NULL;
01748 char *name;
01749 int status;
01750
01751 if (dr==NULL)
01752 return (DR_POINTER_NULL);
01753 if (key==NULL)
01754 return (ATTRNAME_NULL);
01755 if ( (value==NULL) && (attrtype != DR_VOID) )
01756 return (MAKES_NO_SENSE);
01757
01758 name = ConvertToUpper (key);
01759
01760 if ((strcmp (name, "COMMENT") != 0) && (strcmp (name, "HISTORY")))
01761 newattr = dr_search_attr (dr, name);
01762
01763 if (newattr == NULL)
01764 {
01765 newattr = dr_malloc_attribute ();
01766 if (status=dr_set_attrname (newattr, name))
01767 {
01768 free (name); free (newattr); return (status);
01769 }
01770 dr_AddList ((_llist **) &dr->attrib, (_llist *) newattr);
01771 }
01772 free (name);
01773
01774 if (status=dr_set_attrvalue (newattr, value, attrtype))
01775 return status;
01776 if (status=dr_set_comment (newattr, comment))
01777 return status;
01778 return NO_ERROR;
01779 }
01780
01781
01782
01783
01784
01785
01786
01787 int dr_set_data (DR *dr, void *data)
01788 {
01789 if (dr == NULL) return DR_POINTER_NULL;
01790 dr_free_data (dr);
01791 dr->data = data;
01792 return NO_ERROR;
01793 }
01794
01795
01796
01797
01798
01799
01800
01801 int dr_set_fillvalue (DR *dr, void *fillvalue)
01802 {
01803 int datatype, ntot;
01804 void *fillptr;
01805 TIME *td, tb, tm;
01806 long *ld, lb, lm;
01807 int *id, ib, im;
01808 short *sd, sb, sm;
01809 signed char *cd, cb, cm;
01810
01811 if ((datatype = dr_datatype (dr)) < 0) return DR_INVALID_DATATYPE;
01812
01813 if (!fillvalue)
01814 {
01815 if (!(fillptr = dr_std_fillvalue (datatype))) return MALLOC_FAILURE;
01816 }
01817 else
01818 {
01819 if (!(fillptr = dr_malloc_fillvalue (datatype)))
01820 return MALLOC_FAILURE;
01821
01822 switch (datatype)
01823 {
01824 case DR_BYTE:
01825 *(signed char *)fillptr = *(signed char*)fillvalue;
01826 break;
01827 case DR_SHORT:
01828 *(short *)fillptr = *(short*)fillvalue;
01829 break;
01830 case DR_INT:
01831 *(int *)fillptr = *(int*)fillvalue;
01832 break;
01833 case DR_LONG:
01834 *(long *)fillptr = *(long*)fillvalue;
01835 break;
01836 case DR_FLOAT:
01837 *(float *)fillptr = *(float*)fillvalue;
01838 break;
01839 case DR_DOUBLE:
01840 case DR_TIME:
01841 *(double *)fillptr = *(double*)fillvalue;
01842 break;
01843 case DR_COMPLEX:
01844 case DR_STRING:
01845 case DR_LOGICAL:
01846 default:
01847 return DR_INVALID_DATATYPE;
01848 }
01849 }
01850
01851
01852
01853
01854 if (dr->fillval)
01855 {
01856 if (dr->data)
01857 {
01858 ntot = dr_data_length (dr);
01859 switch (datatype)
01860 {
01861 case DR_BYTE:
01862 cd = (signed char *)dr_data (dr);
01863 cm = *(signed char *)dr->fillval;
01864 cb = *(signed char *)fillptr;
01865 while (ntot--)
01866 {
01867 if (*cd == cm) *cd = cb;
01868 cd++;
01869 }
01870 break;
01871 case DR_SHORT:
01872 sd = (short *)dr_data (dr);
01873 sm = *(short *)dr->fillval;
01874 sb = *(short *)fillptr;
01875 while (ntot--)
01876 {
01877 if (*sd == sm) *sd = sb;
01878 sd++;
01879 }
01880 break;
01881 case DR_INT:
01882 id = (int *)dr_data (dr);
01883 im = *(int *)dr->fillval;
01884 ib = *(int *)fillptr;
01885 while (ntot--)
01886 {
01887 if (*id == im) *id = ib;
01888 id++;
01889 }
01890 break;
01891 case DR_LONG:
01892 ld = (long *)dr_data (dr);
01893 lm = *(long *)dr->fillval;
01894 lb = *(long *)fillptr;
01895 while (ntot--)
01896 {
01897 if (*ld == lm)
01898 *ld = lb;
01899 ld++;
01900 }
01901 break;
01902 case DR_TIME:
01903 td = (TIME *)dr_data (dr);
01904 tm = *(TIME *)dr->fillval;
01905 tb = *(TIME *)fillptr;
01906 while (ntot--)
01907 {
01908 if (*td == tm)
01909 *td = tb;
01910 td++;
01911 }
01912 break;
01913 }
01914 }
01915 free (dr->fillval);
01916 }
01917 dr->fillval = fillptr;
01918 return (NO_ERROR);
01919 }
01920
01921 int dr_set_numbytes (DR *dr, int numbytes)
01922 {
01923 if (!dr) return DR_POINTER_NULL;
01924 dr->datumsize = numbytes;
01925 return NO_ERROR;
01926 }
01927
01928
01929
01930
01931
01932
01933 int dr_set_datatype (DR *dr, int datatype)
01934 {
01935 if (!dr) return DR_POINTER_NULL;
01936 if (dr->data) return DR_DATA_POINTER_EXISTS;
01937 dr->datatype = datatype;
01938 dr_set_numbytes (dr, dr_sizeof (datatype));
01939 return NO_ERROR;
01940 }
01941
01942
01943
01944
01945
01946
01947 int dr_set_rank (DR *dr, int rank)
01948 {
01949 int i;
01950
01951 if (!dr) return DR_POINTER_NULL;
01952 if (dr->data) return DR_DATA_POINTER_EXISTS;
01953 if ((rank < 0) || (rank > DR_MAXRANK)) return DR_RANK_ERROR;
01954
01955 dr->rank = rank;
01956 if (dr->length) free (dr->length);
01957 if (!rank) return NO_ERROR;
01958
01959 if (!(dr->length = dr_malloc_length (rank))) return MALLOC_FAILURE;
01960
01961 for (i=0; i<rank; i++)
01962 dr->length[i] = 0;
01963 return NO_ERROR;
01964 }
01965
01966 static void dr_free_one_attr (ATTRIBUTES *attr)
01967 {
01968 if (attr == NULL) return;
01969 if (attr->name) free (attr->name);
01970 if (attr->value) free (attr->value);
01971 if (attr->format) free (attr->format);
01972 if (attr->comment) free (attr->comment);
01973 free (attr);
01974 }
01975
01976
01977
01978
01979
01980
01981
01982
01983 static int dr_remove_attr_mapfn (ATTRIBUTES *thisattr, char *key)
01984 {
01985 ATTRIBUTES *nextattr = thisattr->next;
01986 if (nextattr == NULL) return 0;
01987 if (strcmp (nextattr->name, key) == 0)
01988 {
01989 thisattr->next = nextattr->next;
01990 dr_free_one_attr (nextattr);
01991 return 1;
01992 }
01993 else return 0;
01994 }
01995
01996 int dr_remove_attribute(DR *dr, char *key)
01997 {
01998 if (dr == NULL) return DR_POINTER_NULL;
01999 if (key == NULL) return ATTRIBUTE_NOT_FOUND;
02000 if (dr->attrib == NULL) return ATTR_POINTER_NULL;
02001 if (dr->attrib->name == NULL) return ATTRNAME_NULL;
02002
02003 if (strcmp (dr->attrib->name, key) == 0)
02004 {
02005 dr_free_one_attr ((ATTRIBUTES *)dr_RemoveNthElement
02006 ((_llist **)(&dr->attrib), 1));
02007 return NO_ERROR;
02008 }
02009
02010 if (dr_MapList ((_llist **)&(dr->attrib),
02011 (_llistFn) dr_remove_attr_mapfn, (void *) key)) return NO_ERROR;
02012 return ATTRIBUTE_NOT_FOUND;
02013 }
02014
02015
02016
02017
02018
02019 #include <values.h>
02020
02021 int dr_set_scaling (DR *dr, int bits, double scale, double bias)
02022 {
02023 if (!dr) return DR_POINTER_NULL;
02024 dr->scaling = bits;
02025 dr->bscale = scale;
02026 dr->bzero = bias;
02027 return NO_ERROR;
02028 }
02029
02030 int dr_data_convert (DR *dr, int type_out)
02031 {
02032 double *dpo, *dpn;
02033 float *fo, *fn;
02034 signed int *io, *in, im, ib;
02035 signed short *so, *sn, sm, sb;
02036 signed char *co, *cn, cm, cb;
02037
02038 void *old, *new, *newfill, *oldfill;
02039
02040 double dpb = dr_A_Quiet_dNaN();
02041 float fb = dr_A_Quiet_fNaN();
02042 int type_in, dsize;
02043 size_t ndata;
02044 int checkmiss, countmiss = 0;
02045 int status = NO_ERROR;
02046
02047 if (dr == NULL) return DR_POINTER_NULL;
02048 if (dr->data_avail == 0) return NO_ERROR;
02049 if (dr->data == NULL) return DR_DATA_POINTER_NULL;
02050
02051 switch (type_in = dr_datatype (dr))
02052 {
02053 case DR_BYTE:
02054 case DR_SHORT:
02055 case DR_INT:
02056 case DR_FLOAT:
02057 case DR_DOUBLE:
02058 break;
02059 default:
02060 return DR_INVALID_DATATYPE;
02061 }
02062 if (type_in == type_out) return NO_ERROR;
02063 switch (type_out)
02064 {
02065 case DR_BYTE:
02066 case DR_SHORT:
02067 case DR_INT:
02068 case DR_FLOAT:
02069 case DR_DOUBLE:
02070 break;
02071 default:
02072 return DR_INVALID_DATATYPE;
02073 }
02074
02075 ndata = (size_t)dr_data_length (dr);
02076 dsize = dr_sizeof (type_out);
02077 old = dr_data (dr);
02078 if (!(new = (void *)malloc (ndata * dsize)))
02079 return MALLOC_FAILURE;
02080 if (!(newfill = (void *)malloc (dsize)))
02081 return MALLOC_FAILURE;
02082 checkmiss = (dr->fillval != NULL);
02083 if (checkmiss) oldfill = (void *)dr->fillval;
02084
02085 switch (type_in)
02086 {
02087 case DR_BYTE:
02088 co = (signed char *)old;
02089 if (checkmiss)
02090 cm = *(signed char *)oldfill;
02091 switch (type_out)
02092 {
02093 case DR_BYTE:
02094 break;
02095 case DR_SHORT:
02096 sn = (signed short *)new;
02097 if (checkmiss)
02098 {
02099 sb = (cm == B_MISSING) ? S_MISSING : cm;
02100 while (ndata--)
02101 {
02102 *sn++ = (*co == cm) ? sb : *co;
02103 co++;
02104 }
02105 }
02106 else
02107 {
02108 while (ndata--)
02109 *sn++ = *co++;
02110 }
02111 *(short *)newfill = sb;
02112 break;
02113 case DR_INT:
02114 in = (signed int *)new;
02115 if (checkmiss)
02116 {
02117 ib = (cm == B_MISSING) ? I_MISSING : cm;
02118 while (ndata--)
02119 {
02120 *in++ = (*co == cm) ? ib : *co;
02121 co++;
02122 }
02123 }
02124 else
02125 {
02126 while (ndata--)
02127 *in++ = *co++;
02128 }
02129 *(int *)newfill = ib;
02130 break;
02131 case DR_FLOAT:
02132 fn = (float *)new;
02133 if (checkmiss)
02134 {
02135 while (ndata--)
02136 {
02137 if (*co == cm) *fn++ = fb;
02138 else *fn++ = *co;
02139 co++;
02140 }
02141 }
02142 else
02143 {
02144 while (ndata--)
02145 *fn++ = *co++;
02146 }
02147 countmiss = checkmiss = 0;
02148 break;
02149 case DR_DOUBLE:
02150 dpn = (double *)new;
02151 if (checkmiss)
02152 {
02153 while (ndata--)
02154 {
02155 if (*co == cm) *dpn++ = dpb;
02156 else *dpn++ = *co;
02157 co++;
02158 }
02159 }
02160 else
02161 {
02162 while (ndata--)
02163 *dpn++ = *co++;
02164 }
02165 countmiss = checkmiss = 0;
02166 break;
02167 default:
02168 status = DR_INVALID_DATATYPE;
02169 break;
02170 }
02171 break;
02172 case DR_SHORT:
02173 so = (signed short *)old;
02174 if (checkmiss)
02175 sm = *(signed short *)oldfill;
02176 switch (type_out) {
02177 case DR_BYTE:
02178 cn = (signed char *)new;
02179 if (checkmiss) {
02180 cb = (sm < SCHAR_MIN || sm > SCHAR_MAX) ? B_MISSING : sm;
02181 while (ndata--) {
02182 if (*so == sm) *cn++ = cb;
02183 else if (*so < SCHAR_MIN || *so > SCHAR_MAX) {
02184 *cn++ = cb;
02185 countmiss++;
02186 } else *cn++ = *so;
02187 so++;
02188 }
02189 } else {
02190 cb = B_MISSING;
02191 while (ndata--) {
02192 if (*so < SCHAR_MIN || *so > SCHAR_MAX) {
02193 *cn++ = cb;
02194 countmiss++;
02195 } else *cn++ = *so;
02196 so++;
02197 }
02198 }
02199 *(signed char *)newfill = cb;
02200 break;
02201 case DR_SHORT:
02202 break;
02203 case DR_INT:
02204 in = (signed int *)new;
02205 if (checkmiss) {
02206 ib = (sm == S_MISSING) ? I_MISSING : sm;
02207 while (ndata--) {
02208 *in++ = (*so == sm) ? ib : *so;
02209 so++;
02210 }
02211 } else {
02212 while (ndata--)
02213 *in++ = *so++;
02214 }
02215 *(int *)newfill = ib;
02216 break;
02217 case DR_FLOAT:
02218 fn = (float *)new;
02219 if (checkmiss) {
02220 while (ndata--) {
02221 if (*so == sm) *fn++ = fb;
02222 else *fn++ = *so;
02223 so++;
02224 }
02225 } else {
02226 while (ndata--)
02227 *fn++ = *so++;
02228 }
02229 countmiss = checkmiss = 0;
02230 break;
02231 case DR_DOUBLE:
02232 dpn = (double *)new;
02233 if (checkmiss) {
02234 while (ndata--) {
02235 if (*so == sm) *dpn++ = dpb;
02236 else *dpn++ = *so;
02237 so++;
02238 }
02239 } else {
02240 while (ndata--)
02241 *dpn++ = *so++;
02242 }
02243 countmiss = checkmiss = 0;
02244 break;
02245 default:
02246 status = DR_INVALID_DATATYPE;
02247 break;
02248 }
02249 break;
02250 case DR_INT:
02251 io = (int *)old;
02252 if (checkmiss)
02253 im = *(signed int *)oldfill;
02254 switch (type_out) {
02255 case DR_BYTE:
02256 cn = (signed char *)new;
02257 if (checkmiss) {
02258 cb = (im < SCHAR_MIN || im > SCHAR_MAX) ? B_MISSING : im;
02259 while (ndata--) {
02260 if (*io == im) *cn++ = cb;
02261 else if (*io < SCHAR_MIN || *io > SCHAR_MAX) {
02262 *cn++ = cb;
02263 countmiss++;
02264 } else *cn++ = *io;
02265 io++;
02266 }
02267 } else {
02268 cb = B_MISSING;
02269 while (ndata--) {
02270 if (*io < SCHAR_MIN || *io > SCHAR_MAX) {
02271 *cn++ = cb;
02272 countmiss++;
02273 } else *cn++ = *io;
02274 io++;
02275 }
02276 }
02277 *(signed char *)newfill = cb;
02278 break;
02279 case DR_SHORT:
02280 sn = (signed short *)new;
02281 if (checkmiss) {
02282 sb = (im < SHRT_MIN || im > SHRT_MAX) ? S_MISSING : im;
02283 while (ndata--) {
02284 if (*io == im) *sn++ = sb;
02285 if (*io < SHRT_MIN || *io > SHRT_MAX) {
02286 *sn++ = sb;
02287 countmiss++;
02288 } else *sn++ = *io;
02289 io++;
02290 }
02291 } else {
02292 sb = S_MISSING;
02293 while (ndata--) {
02294 if (*io < SHRT_MIN || *io > SHRT_MAX) {
02295 *sn++ = sb;
02296 countmiss++;
02297 } else *sn++ = *io;
02298 io++;
02299 }
02300 }
02301 *(signed short *)newfill = sb;
02302 break;
02303 case DR_INT:
02304 break;
02305 case DR_FLOAT:
02306 fn = (float *)new;
02307 if (checkmiss) {
02308 while (ndata--) {
02309 if (*io == im) *fn++ = fb;
02310 else *fn++ = *io;
02311 io++;
02312 }
02313 } else {
02314 while (ndata--)
02315 *fn++ = *io++;
02316 }
02317 countmiss = checkmiss = 0;
02318 break;
02319 case DR_DOUBLE:
02320 dpn = (double *)new;
02321 if (checkmiss) {
02322 while (ndata--) {
02323 if (*io == im) *dpn++ = dpb;
02324 else *dpn++ = *io;
02325 io++;
02326 }
02327 } else {
02328 while (ndata--)
02329 *dpn++ = *io++;
02330 }
02331 countmiss = checkmiss = 0;
02332 break;
02333 default:
02334 status = DR_INVALID_DATATYPE;
02335 break;
02336 }
02337 break;
02338 case DR_FLOAT:
02339 fo = (float *)old;
02340 switch (type_out) {
02341 case DR_BYTE:
02342 cn = (signed char *)new;
02343 cb = B_MISSING;
02344 while (ndata--) {
02345 if (IsfNaN (*fo)) {
02346 *cn++ = cb;
02347 checkmiss = 1;
02348 }
02349 else if (*fo < SCHAR_MIN || *fo > SCHAR_MAX) {
02350 *cn++ = cb;
02351 countmiss++;
02352 } else *cn++ = (*fo < 0.0) ? *fo - 0.5 : *fo + 0.5;
02353 fo++;
02354 }
02355 *(signed char *)newfill = cb;
02356 dr_set_scaling (dr, 0, 1.0, 0.0);
02357 break;
02358 case DR_SHORT:
02359 sn = (signed short *)new;
02360 sb = S_MISSING;
02361 while (ndata--) {
02362 if (IsfNaN (*fo)) {
02363 *sn++ = sb;
02364 checkmiss = 1;
02365 }
02366 else if (*fo < SHRT_MIN || *fo > SHRT_MAX) {
02367 *sn++ = sb;
02368 countmiss++;
02369 } else *sn++ = (*fo < 0.0) ? *fo - 0.5 : *fo + 0.5;
02370 fo++;
02371 }
02372 *(signed short *)newfill = sb;
02373 dr_set_scaling (dr, 0, 1.0, 0.0);
02374 break;
02375 case DR_INT:
02376 in = (signed int *)new;
02377 ib = I_MISSING;
02378 while (ndata--) {
02379 if (IsfNaN (*fo)) {
02380 *in++ = ib;
02381 checkmiss = 1;
02382 }
02383 else if (*fo < INT_MIN || *fo > INT_MAX) {
02384 *in++ = ib;
02385 countmiss++;
02386 } else *in++ = (*fo < 0.0) ? *fo - 0.5 : *fo + 0.5;
02387 fo++;
02388 }
02389 *(signed int *)newfill = ib;
02390 dr_set_scaling (dr, 0, 1.0, 0.0);
02391 break;
02392 case DR_FLOAT:
02393 break;
02394 case DR_DOUBLE:
02395 dpn = (double *)new;
02396 while (ndata--) {
02397 if (IsfNaN (*fo))
02398 *dpn++ = dpb;
02399 else
02400 *dpn++ = *fo;
02401 fo++;
02402 }
02403 countmiss = checkmiss = 0;
02404 break;
02405 default:
02406 status = DR_INVALID_DATATYPE;
02407 break;
02408 }
02409 break;
02410 case DR_DOUBLE:
02411 dpo = (double *)old;
02412 switch (type_out) {
02413 case DR_BYTE:
02414 cn = (signed char *)new;
02415 cb = B_MISSING;
02416 while (ndata--) {
02417 if (IsdNaN (*dpo)) {
02418 *cn++ = cb;
02419 checkmiss = 1;
02420 }
02421 else if (*dpo < SCHAR_MIN || *dpo > SCHAR_MAX) {
02422 *cn++ = cb;
02423 countmiss++;
02424 } else *cn++ = (*dpo < 0.0) ? *dpo - 0.5 : *dpo + 0.5;
02425 dpo++;
02426 }
02427 *(signed char *)newfill = cb;
02428 break;
02429 case DR_SHORT:
02430 sn = (signed short *)new;
02431 sb = S_MISSING;
02432 while (ndata--) {
02433 if (IsdNaN (*dpo)) {
02434 *sn++ = sb;
02435 checkmiss = 1;
02436 }
02437 else if (*dpo < SHRT_MIN || *dpo > SHRT_MAX) {
02438 *sn++ = sb;
02439 countmiss++;
02440 } else *sn++ = (*dpo < 0.0) ? *dpo - 0.5 : *dpo + 0.5;
02441 dpo++;
02442 }
02443 *(signed short *)newfill = sb;
02444 break;
02445 case DR_INT:
02446 in = (signed int *)new;
02447 ib = I_MISSING;
02448 while (ndata--) {
02449 if (IsdNaN (*dpo)) {
02450 *in++ = ib;
02451 checkmiss = 1;
02452 }
02453 else if (*dpo < INT_MIN || *dpo > INT_MAX) {
02454 *in++ = ib;
02455 countmiss++;
02456 } else *in++ = (*dpo < 0.0) ? *dpo - 0.5 : *dpo + 0.5;
02457 dpo++;
02458 }
02459 *(signed int *)newfill = ib;
02460 break;
02461 case DR_FLOAT:
02462 fn = (float *)new;
02463 while (ndata--) {
02464 if (IsfNaN (*dpo))
02465 *fn++ = fb;
02466 else if (*dpo > FLT_MAX || *dpo < -FLT_MAX) {
02467 *fn++ = fb;
02468 countmiss++;
02469 } else
02470 *fn++ = *dpo;
02471 dpo++;
02472 }
02473 if (countmiss) status = DATA_OUT_OF_RANGE;
02474 countmiss = checkmiss = 0;
02475 break;
02476 case DR_DOUBLE:
02477 break;
02478 default:
02479 status = DR_INVALID_DATATYPE;
02480 break;
02481 }
02482 break;
02483 default:
02484 status = DR_INVALID_DATATYPE;
02485 break;
02486 }
02487 if (status == DR_INVALID_DATATYPE) {
02488 free (new);
02489 free (newfill);
02490 return status;
02491 }
02492
02493 dr_free_data (dr);
02494 dr_set_datatype (dr, type_out);
02495 dr_set_data (dr, new);
02496 if (countmiss || checkmiss)
02497 dr_set_fillvalue (dr, newfill);
02498 else {
02499 free (newfill);
02500 free (dr->fillval);
02501 dr->fillval = NULL;
02502 }
02503 if (countmiss) status = DATA_OUT_OF_RANGE;
02504 return status;
02505 }
02506
02507 int dr_scale_data (DR *dr, double scale, double bias) {
02508 double *dd, datum;
02509 float *fd;
02510 unsigned int fill;
02511 int dtype, ndata, out = 0, setfill = 0;
02512 int status = NO_ERROR;
02513
02514 if (scale == 1.0 && bias == 0.0) return status;
02515 if (dr == NULL) return (status = DR_POINTER_NULL);
02516 if (dr->data == NULL) return (status = DR_DATA_POINTER_NULL);
02517
02518 ndata = dr_data_length (dr);
02519
02520 if (dr->fillval) {
02521 fill = *(unsigned int *)dr->fillval;
02522 setfill = 1;
02523 }
02524
02525 switch (dtype = dr_datatype (dr)) {
02526 case DR_BYTE:
02527 case DR_SHORT:
02528 dr_data_convert (dr, DR_FLOAT);
02529 dr_scale_data (dr, scale, bias);
02530 status = dr_data_convert (dr, dtype);
02531 if (setfill) dr_set_fillvalue (dr, &fill);
02532 return (status);
02533 case DR_INT:
02534 dr_data_convert (dr, DR_DOUBLE);
02535 dr_scale_data (dr, scale, bias);
02536 status = dr_data_convert (dr, dtype);
02537 if (setfill) dr_set_fillvalue (dr, &fill);
02538 return (status);
02539 case DR_FLOAT:
02540 fd = (float *)dr->data;
02541 while (ndata--) {
02542 if (IsfNaN (*fd))
02543 fd++;
02544 else {
02545 datum = (*fd * scale) + bias;
02546 if (datum > FLT_MAX || datum < -FLT_MAX)
02547 out++;
02548 *fd++ = datum;
02549 }
02550 }
02551 break;
02552 case DR_DOUBLE:
02553 dd = (double *)dr->data;
02554 while (ndata--) {
02555 if (IsdNaN (*dd))
02556 dd++;
02557 else {
02558 datum = scale * *dd + bias;
02559 if (datum > DBL_MAX || datum < -DBL_MAX)
02560 out++;
02561 *dd++ = datum;
02562 }
02563 }
02564 break;
02565 default:
02566 return (status = DR_INVALID_DATATYPE);
02567 }
02568
02569 if (dr->scaling) {
02570 dr->bscale /= scale;
02571 dr->bzero -= bias * dr->bscale;
02572 }
02573 return (out) ? DATA_OUT_OF_RANGE : 0;
02574 }
02575
02576
02577
02578
02579
02580 static int dr_flip (void *data, long length, int size) {
02581 long i,j;
02582 char *c, t;
02583 unsigned short *s;
02584 unsigned int *l;
02585
02586 if (data == NULL) return DR_DATA_POINTER_NULL;
02587
02588 if (size == 2) {
02589 s = (unsigned short *)data;
02590 for (i=0; i<length; i++, s++)
02591 *s = (*s<<8) | (*s>>8);
02592 } else if (size == 4) {
02593 l = (unsigned int *)data;
02594 for (i=0; i<length; i++, l++)
02595 *l = (*l<<24) | ((*l&0xff00)<<8) | ((*l&0xff0000)>>8) | (*l>>24);
02596 } else {
02597 c = (char *)data;
02598 for (i=0; i<length; i++, c+=size)
02599 for (j=0; j<(size/2); j++) {
02600 t=*(c+j);
02601 *(c+j)=*(c+size-j-1);
02602 *(c+size-j-1)=t;
02603 }
02604 }
02605 return 0;
02606 }
02607
02608 int dr_flip_data (DR *dr) {
02609 if (dr == NULL) return DR_POINTER_NULL;
02610 return dr_flip (dr->data, dr_data_length (dr), dr->datumsize);
02611 }
02612
02613
02614
02615
02616
02617 #include <stdio.h>
02618 #include <string.h>
02619 #include <ctype.h>
02620 #include <limits.h>
02621
02622 #define FITS_KWSIZE 8
02623 #define FITS_VALSIZE 70
02624 #define FITS_CARDSIZE 80
02625 #define FITS_NCARDS 36
02626
02627
02628 static unsigned short ReadDataType (char *line) {
02629 char str[FITS_VALSIZE + 1];
02630
02631 return (sscanf (line, "%s", str) == 1) ? header_value_type (str) : DR_VOID;
02632 }
02633
02634 static char *ReadComment (char *line, int datatype) {
02635 char *end, *str, *pos;
02636 int len;
02637 if (datatype == DR_STRING) {
02638 if (end = strrchr (line, '\''))
02639 line = end;
02640 } else if (end = strchr (line, ' '))
02641 line = end;
02642
02643 if (pos = strchr (line, '/')) {
02644 if (pos = FirstNonWhite (pos + 1)) {
02645 end = LastNonWhite (pos);
02646 len = end - pos + 2;
02647 str = dr_malloc_string (len + 1);
02648 strncpy (str, pos, len);
02649 str[len] = 0;
02650 return str;
02651 }
02652 }
02653 return NULL;
02654 }
02655
02656 static ATTRIBUTES *GetHeaderRecord (DR *dr, FILE *fp) {
02657 ATTRIBUTES *attr;
02658 char *c1, *c2, *line;
02659 int i, pos=0;
02660 char card[FITS_CARDSIZE+1];
02661
02662 card[FITS_CARDSIZE] = 0;
02663
02664 if (!fread (card, FITS_CARDSIZE, 1, fp)) {
02665 return NULL;
02666 }
02667
02668 for (i=0; i<FITS_CARDSIZE; i++)
02669 if (!card[i]) card[i] = ' ';
02670
02671 attr = dr_malloc_attribute ();
02672 attr->name = dr_malloc_string (FITS_KWSIZE);
02673 sscanf (card, "%8s", attr->name);
02674
02675 if (!strcmp (attr->name, "COMMENT")) {
02676 line = card + FITS_KWSIZE;
02677
02678 dr_append_comment (dr, line);
02679 dr_append_comment (dr, "\n");
02680 return attr;
02681 }
02682
02683 if (!strcmp (attr->name, "HISTORY")) {
02684 line = card + FITS_KWSIZE;
02685 dr_append_history (dr, line);
02686 dr_append_history (dr, "\n");
02687 return attr;
02688 }
02689
02690 line = card + FITS_KWSIZE + 2;
02691 attr->datatype = ReadDataType (line);
02692
02693 switch (attr->datatype) {
02694 case DR_VOID:
02695 attr->value = NULL;
02696 break;
02697 case DR_LOGICAL:
02698 attr->value = (char*)malloc (sizeof (char) + 1);
02699 sscanf (line, "%1s", (char *)attr->value);
02700 break;
02701 case DR_STRING:
02702 if ((c1 = strchr (line, '\'')) && (c2 = strrchr (c1 + 1, '\'')))
02703 c1++;
02704 else {
02705
02706 for (c1 = line; *c1 == ' '; c1++)
02707 ;
02708
02709 for (c2=c1; *c2 && *c2 != ' '; c2++)
02710 ;
02711 }
02712 *c2 = '\0';
02713 pos = c2 + 1 - line;
02714 while (c2 > c1 && *(c2-1) == ' ')
02715 *--c2 = '\0';
02716 attr->value = dr_malloc_string (c2 - c1);
02717 strcpy (attr->value, c1);
02718 break;
02719 case DR_LONG:
02720 attr->value = (long *)malloc (sizeof (long));
02721 sscanf (line, "%ld", (long *)attr->value);
02722 break;
02723 case DR_DOUBLE:
02724 attr->value = (double *)malloc (sizeof (double));
02725 sscanf (line, "%lf", (double *)attr->value);
02726 break;
02727 default:
02728 attr->value = NULL;
02729
02730
02731
02732 }
02733
02734 attr->comment = ReadComment (line + pos, attr->datatype);
02735 return attr;
02736 }
02737
02738 static void SetDiminfo (DR *dr) {
02739 char naxisn[FITS_KWSIZE + 1];
02740 int i, naxis, *naxisArr;
02741 void *ptr;
02742
02743 ptr = dr_search_attrvalue (dr, "NAXIS");
02744 if (ptr == NULL) return;
02745 naxis = *(long *)ptr;
02746 dr_remove_attribute (dr, "NAXIS");
02747 dr->rank = naxis;
02748 if (naxis == 0) return;
02749 naxisArr = dr_malloc_length (naxis);
02750
02751 for (i = 0; i < naxis; i++) {
02752 sprintf (naxisn, "NAXIS%d", i+1);
02753 ptr = dr_search_attrvalue (dr, naxisn);
02754 if (ptr == NULL) return;
02755 naxisArr[i] = *(int*)ptr;
02756 dr_remove_attribute (dr, naxisn);
02757 }
02758 if (dr->length) free (dr->length);
02759 dr->length = naxisArr;
02760 }
02761
02762 static void ProcessAttrList (DR *dr, int conforming) {
02763 void *vval;
02764 long int lmiss;
02765 int imiss;
02766 short smiss;
02767 unsigned char bmiss;
02768
02769 if (!conforming) {
02770 if (!(vval = dr_search_attrvalue (dr, "BITPIX"))) {
02771
02772
02773
02774
02775 return;
02776 }
02777 switch (*(long *)vval) {
02778 case (8):
02779 dr_set_datatype (dr, DR_BYTE);
02780 break;
02781 case (16):
02782 dr_set_datatype (dr, DR_SHORT);
02783 break;
02784 case (32):
02785 dr_set_datatype (dr, DR_INT);
02786 break;
02787 case (64):
02788 if (sizeof (long) > sizeof (int)) {
02789 dr_set_datatype (dr, DR_LONG);
02790 break;
02791 }
02792
02793
02794
02795
02796
02797 return;
02798 case (-32):
02799 dr_set_datatype (dr, DR_FLOAT);
02800 break;
02801 case (-64):
02802 dr_set_datatype (dr, DR_DOUBLE);
02803 break;
02804 default:
02805
02806
02807
02808
02809 return;
02810 }
02811 dr_remove_attribute (dr, "BITPIX");
02812 SetDiminfo (dr);
02813 }
02814
02815 dr_set_scaling (dr, 0, 1.0, 0.0);
02816 if (vval = dr_search_attrvalue (dr, "BSCALE")) {
02817 switch (dr_datatype (dr)) {
02818 case (DR_BYTE):
02819 dr_set_scaling (dr, 8, *(double *)vval, dr_bzero (dr));
02820 break;
02821 case (DR_SHORT):
02822 dr_set_scaling (dr, 16, *(double *)vval, dr_bzero (dr));
02823 break;
02824 case (DR_INT):
02825 dr_set_scaling (dr, 32, *(double *)vval, dr_bzero (dr));
02826 break;
02827 case (DR_LONG):
02828 dr_set_scaling (dr, 64, *(double *)vval, dr_bzero (dr));
02829 break;
02830 }
02831 dr_remove_attribute (dr, "BSCALE");
02832 }
02833 if (vval = dr_search_attrvalue (dr, "BZERO")) {
02834 switch (dr_datatype (dr)) {
02835 case (DR_BYTE):
02836 dr_set_scaling (dr, 8, dr_bscale (dr), *(double *)vval);
02837 break;
02838 case (DR_SHORT):
02839 dr_set_scaling (dr, 16, dr_bscale (dr), *(double *)vval);
02840 break;
02841 case (DR_INT):
02842 dr_set_scaling (dr, 32, dr_bscale (dr), *(double *)vval);
02843 break;
02844 case (DR_LONG):
02845 dr_set_scaling (dr, 64, dr_bscale (dr), *(double *)vval);
02846 break;
02847 }
02848 dr_remove_attribute (dr, "BZERO");
02849 }
02850
02851 if (vval = dr_search_attrvalue (dr, "BLANK")) {
02852
02853
02854 lmiss = *(long *)vval;
02855 switch (dr->datatype) {
02856 case (DR_INT):
02857 if (lmiss < INT_MIN || lmiss > INT_MAX) {
02858 ;
02859
02860
02861
02862
02863 } else {
02864 imiss = lmiss;
02865 dr_set_fillvalue (dr, &imiss);
02866 }
02867 break;
02868 case (DR_SHORT):
02869 if (lmiss < SHRT_MIN || lmiss > SHRT_MAX) {
02870 ;
02871
02872
02873
02874
02875 } else {
02876 smiss = lmiss;
02877 dr_set_fillvalue (dr, &smiss);
02878 }
02879 break;
02880 case (DR_BYTE):
02881 bmiss = *(long *)vval;
02882 if (lmiss < 0 || lmiss > UCHAR_MAX) {
02883 ;
02884
02885
02886
02887
02888 } else {
02889 bmiss = lmiss;
02890 dr_set_fillvalue (dr, &bmiss);
02891 }
02892 break;
02893 case (DR_LONG):
02894 dr_set_fillvalue (dr, &lmiss);
02895 break;
02896 }
02897 dr_remove_attribute (dr, "BLANK");
02898 }
02899 }
02900
02901 int read_fits_head (DR *dr, FILE *fp) {
02902 ATTRIBUTES *attr;
02903 int ival, remain, recs = 0;
02904 int file_conforms = 1;
02905 int status = NO_ERROR;
02906 char naxisn[FITS_KWSIZE + 1];
02907
02908 if (!dr) return DR_POINTER_NULL;
02909
02910 dr_free_attr (dr->attrib);
02911 dr->attrib = NULL;
02912
02913 rewind (fp);
02914
02915 if (!(attr = GetHeaderRecord (dr, fp))) return (FITS_ERROR);
02916 if (strcmp (dr_attrname (attr), "SIMPLE")) {
02917
02918 dr_free_attr (attr);
02919 return FITS_ERROR;
02920 }
02921 if (!dr_attrvalue_str (attr) || strcmp (dr_attrvalue_str (attr), "T")) {
02922
02923
02924
02925 file_conforms = 0;
02926 }
02927 dr_free_attr (attr);
02928 recs++;
02929 if (file_conforms) {
02930
02931 if (!(attr = GetHeaderRecord (dr, fp))) return (FITS_ERROR);
02932 if (strcmp (dr_attrname (attr), "BITPIX")) {
02933
02934
02935
02936 dr_free_attr (attr);
02937 return FITS_ERROR;
02938 } else if (!dr_attrvalue (attr)) {
02939
02940
02941
02942
02943 dr_free_attr (attr);
02944 return FITS_ERROR;
02945 }
02946 dr_free_data (dr);
02947
02948 ival = *(long *)dr_attrvalue (attr);
02949 switch (ival) {
02950 case (8):
02951 dr_set_datatype (dr, DR_BYTE);
02952 break;
02953 case (16):
02954 dr_set_datatype (dr, DR_SHORT);
02955 break;
02956 case (32):
02957 dr_set_datatype (dr, DR_INT);
02958 break;
02959 case (64):
02960 if (sizeof (long) > sizeof (int)) {
02961 dr_set_datatype (dr, DR_LONG);
02962
02963
02964
02965
02966 break;
02967 }
02968
02969
02970
02971 return FITS_ERROR;
02972 case (-32):
02973 dr_set_datatype (dr, DR_FLOAT);
02974 break;
02975 case (-64):
02976 dr_set_datatype (dr, DR_DOUBLE);
02977 break;
02978 default:
02979
02980
02981
02982 dr_free_attr (attr);
02983 return FITS_ERROR;
02984 }
02985 dr_free_attr (attr);
02986 recs++;
02987
02988 if (!(attr = GetHeaderRecord (dr, fp))) return FITS_ERROR;
02989 if (strcmp (dr_attrname (attr), "NAXIS")) {
02990
02991
02992
02993 dr_free_attr (attr);
02994 return FITS_ERROR;
02995 } else if (!dr_attrvalue (attr)) {
02996
02997
02998
02999
03000 dr_free_attr (attr);
03001 return FITS_ERROR;
03002 }
03003 ival = *(long *)dr_attrvalue (attr);
03004 if (ival < 0 || ival > 999) {
03005
03006
03007
03008 return FITS_ERROR;
03009 }
03010 dr_set_rank (dr, ival);
03011 if (ival) {
03012 int *naxisArr = dr_malloc_length (ival);
03013 int n = 0;
03014
03015 while (n < ival) {
03016 sprintf (naxisn, "NAXIS%d", n + 1);
03017 if (!(attr = GetHeaderRecord (dr, fp))) {
03018
03019
03020
03021 return FITS_ERROR;
03022 } else if (strcmp (dr_attrname (attr), naxisn)) {
03023
03024
03025
03026
03027 return FITS_ERROR;
03028 } else if (!dr_attrvalue (attr)) {
03029
03030
03031
03032
03033 return FITS_ERROR;
03034 }
03035 naxisArr[n++] = *(long *)dr_attrvalue (attr);
03036 recs++;
03037 }
03038 dr->length = naxisArr;
03039 }
03040 recs++;
03041 }
03042 while (!status) {
03043 attr = GetHeaderRecord (dr, fp);
03044 if (!attr) {
03045 status = FITS_ERROR;
03046
03047
03048
03049 break;
03050 }
03051 recs++;
03052 if (strcmp (attr->name, "END") != 0) {
03053 if (!strcmp (attr->name, "COMMENT") ||
03054 !strcmp (attr->name, "HISTORY"))
03055 dr_free_attr (attr);
03056 else
03057
03058 dr_AddList ((_llist **) &(dr->attrib), (_llist *) attr);
03059 } else {
03060 dr_free_attr (attr);
03061 ProcessAttrList (dr, file_conforms);
03062
03063 remain = (FITS_NCARDS - recs) % FITS_NCARDS;
03064 if (remain < 0) remain += FITS_NCARDS;
03065 if (remain % FITS_NCARDS)
03066 if (fseek (fp, remain * FITS_CARDSIZE, SEEK_CUR))
03067 status = FITS_ERROR;
03068 return status;
03069 }
03070 }
03071 return status;
03072 }
03073
03074 static int read_fits_data (DR *dr, FILE *fp) {
03075 int status = NO_ERROR;
03076 long nbytes;
03077 if (status = dr_create_data(dr)) return status;
03078 if (dr->data == NULL) return NO_ERROR;
03079 nbytes = dr_data_length (dr) * dr_numbytes (dr);
03080
03081 if (fread (dr->data, nbytes, 1, fp) == 0) {
03082 status = READ_FAILURE;
03083 dr_free_data (dr);
03084 }
03085 else
03086 dr->data_avail = 1;
03087
03088 #ifdef IEEE_EL
03089 dr_flip_data (dr);
03090 #endif
03091 return status;
03092 }
03093
03094 DR *dr_read_fits_header (FILE *in, int *status)
03095 {
03096 DR *dr;
03097
03098 if (!in)
03099 {
03100 *status = FILE_POINTER_NULL;
03101 return NULL;
03102 }
03103 if (!(dr = dr_create ()))
03104 {
03105 *status = DR_CREATE_FAILURE;
03106 return (dr);
03107 }
03108 if (read_fits_head (dr, in))
03109 {
03110 dr_free (&dr);
03111 return (dr);
03112 }
03113 *status = NO_ERROR;
03114 return (dr);
03115 }
03116
03117 DR *dr_read_fits (FILE *in, int *status) {
03118 DR *dr;
03119
03120 if (!in) {
03121 *status = FILE_POINTER_NULL;
03122 return NULL;
03123 }
03124 if (!(dr = dr_create ())) {
03125 *status = DR_CREATE_FAILURE;
03126 return (dr);
03127 }
03128 if (read_fits_head (dr, in)) {
03129 dr_free (&dr);
03130 return (dr);
03131 }
03132 if (read_fits_data (dr, in)) {
03133
03134 ;
03135 }
03136 if (dr->scaling) {
03137
03138 double scale = dr_bscale (dr);
03139 double bias = dr_bzero (dr);
03140 int dtype = (dr->scaling > 16) ? DR_DOUBLE : DR_FLOAT;
03141 dr_data_convert (dr, dtype);
03142 dr_scale_data (dr, scale, bias);
03143 dr_set_scaling (dr, dr->scaling, scale, bias);
03144 }
03145 *status = NO_ERROR;
03146 return (dr);
03147 }
03148
03149 static char *AttrValue (ATTRIBUTES *attr)
03150 {
03151 static char str[FITS_CARDSIZE + 1];
03152 int len;
03153
03154 str[0] = '\0';
03155 if (!attr) return (str);
03156 if (attr->datatype == DR_VOID) return (str);
03157 switch (attr->datatype)
03158 {
03159 case (DR_LOGICAL):
03160 sprintf (str, "= %*.*s", 20, 1, dr_attrvalue_str (attr));
03161 break;
03162 case DR_BYTE:
03163 case DR_SHORT:
03164 case DR_INT:
03165 case DR_LONG:
03166 case DR_FLOAT:
03167 case DR_DOUBLE:
03168 sprintf (str, "= %s", dr_attrvalue_str (attr));
03169 break;
03170 case DR_STRING:
03171 case DR_TIME:
03172 len = strlen (dr_attrvalue_str (attr));
03173 if (len > FITS_VALSIZE - 2) len = FITS_VALSIZE - 2;
03174
03175 sprintf (str, "= '%.*s'", len, dr_attrvalue_str (attr));
03176 break;
03177 }
03178 return (str);
03179 }
03180
03181 static int PutHeaderRecord (ATTRIBUTES *attr, FILE *fp) {
03182 int status = 0;
03183 int rem = FITS_CARDSIZE;
03184 char str[FITS_CARDSIZE + 1];
03185 static char blank[] =
03186 {" "};
03187
03188 if (!attr) return ATTR_POINTER_NULL;
03189 if (!attr->name) return ATTRNAME_NULL;
03190
03191 sprintf (str, "%-*.*s", FITS_KWSIZE, FITS_KWSIZE, attr->name);
03192 rem -= FITS_KWSIZE;
03193 strncat (str, AttrValue (attr), rem);
03194 rem = FITS_CARDSIZE - strlen (str);
03195 if (attr->comment && (rem > 3)) {
03196 strcat (str, " / ");
03197 strncat (str, attr->comment, rem - 3);
03198 }
03199 rem = FITS_CARDSIZE - strlen (str);
03200 strncat (str, blank, rem);
03201 if (fwrite (str, FITS_CARDSIZE, 1, fp) != 1) {
03202
03203
03204
03205 status = WRITE_FAILURE;
03206 }
03207 return status;
03208 }
03209
03210 static int PutAttributes (DR *dr, FILE *fp)
03211 {
03212 int numput= 0;
03213 ATTRIBUTES *attr = dr->attrib;
03214
03215 while (attr)
03216 {
03217 if (strcmp (attr->name, "SIMPLE") &&
03218 strcmp (attr->name, "BITPIX") &&
03219 strncmp (attr->name, "NAXIS", 5)
03220 && strcmp (attr->name, "BSCALE") &&
03221 strcmp (attr->name, "BZERO") &&
03222 strcmp (attr->name, "BLANK") &&
03223 strcmp (attr->name, "END"))
03224 {
03225
03226 PutHeaderRecord (attr, fp);
03227
03228 numput++;
03229 }
03230
03231
03232
03233
03234
03235 attr = dr_next_attr (attr);
03236 }
03237 return numput;
03238 }
03239
03240 static int PutOneMandatory (char *key, void *value, int attrtype,
03241 char *comment, FILE *fp) {
03242 int status;
03243 ATTRIBUTES *temp;
03244
03245 if (!(temp = dr_malloc_attribute())) return 0;
03246 dr_set_attrname (temp, key);
03247 dr_set_attrvalue (temp, value, attrtype);
03248 if (comment) dr_set_comment (temp, comment);
03249 else dr_set_comment (temp, "");
03250 status = PutHeaderRecord (temp, fp);
03251 dr_free_attr (temp);
03252 return 1;
03253 }
03254
03255 static int PutMandatory (DR *dr, FILE *fp) {
03256 int bitpix, datatype, rank, dim, i;
03257 char simple[FITS_VALSIZE+1], naxis[FITS_KWSIZE+1];
03258 int numput = 0;
03259
03260 sprintf (simple, "file conforms with FITS standard; JSOC %s", dr_lib_version);
03261 numput += PutOneMandatory ("SIMPLE", "T", DR_LOGICAL, simple, fp);
03262
03263 datatype = dr_datatype (dr);
03264 bitpix = 8 * dr_numbytes (dr);
03265 if (bitpix == 0 || bitpix % 8) {
03266 bitpix = 8;
03267
03268
03269
03270
03271 }
03272 if (datatype == DR_FLOAT || datatype == DR_DOUBLE || datatype == DR_TIME)
03273 bitpix *= -1;
03274 numput += PutOneMandatory ("BITPIX", &bitpix, DR_INT, "", fp);
03275 rank = dr_rank (dr);
03276 numput += PutOneMandatory ("NAXIS", &rank, DR_INT, "", fp);
03277 for (i=0; i<rank; i++) {
03278 sprintf (naxis, "NAXIS%d", i+1);
03279 dim = dr_dim_n (dr, i);
03280 numput += PutOneMandatory (naxis, &dim, DR_INT, "", fp);
03281 }
03282 if (dr->scaling) {
03283 numput += PutOneMandatory ("BSCALE", &dr->bscale, DR_DOUBLE, NULL, fp);
03284 numput += PutOneMandatory ("BZERO", &dr->bzero, DR_DOUBLE, NULL, fp);
03285 }
03286
03287 if (dr->fillval) {
03288 switch (dr->datatype) {
03289 case (DR_BYTE):
03290 case (DR_SHORT):
03291 case (DR_INT):
03292 case (DR_LONG):
03293 case (DR_TIME):
03294 numput +=
03295 PutOneMandatory ("BLANK", dr->fillval, dr->datatype, NULL, fp);
03296 }
03297 }
03298 return numput;
03299 }
03300
03301 static int PutCommentary (DR *dr, FILE *fp) {
03302 int rlen;
03303 int numput = 0, rem = 0;
03304 char *str;
03305 char c = '\0', sp = '\x20';
03306
03307 if (str = dr->comment) {
03308 rlen = strlen (str);
03309 numput++;
03310 if (fwrite ("COMMENT ", 8, 1, fp) != 1) {
03311 ;
03312
03313
03314
03315
03316 }
03317 rem = FITS_CARDSIZE - 8;
03318 while (rlen--) {
03319 if ((c = *(str++)) == '\n') {
03320 if (rem < (FITS_CARDSIZE - 8)) {
03321 while (rem) {
03322 fputc (sp, fp);
03323 rem--;
03324 }
03325 }
03326 } else {
03327 fputc (c, fp);
03328 rem--;
03329 }
03330 if (rem == 0 && rlen && *str != '\n') {
03331 numput++;
03332 if (fwrite ("COMMENT ", 8, 1, fp) != 1) {
03333
03334
03335
03336
03337 ;
03338 }
03339 rem = FITS_CARDSIZE - 8;
03340 }
03341 }
03342 while (rem--)
03343 fputc (sp, fp);
03344 }
03345
03346 if (str = dr->history) {
03347 rlen = strlen (str);
03348 numput++;
03349 if (fwrite ("HISTORY ", 8, 1, fp) != 1) {
03350 ;
03351
03352
03353
03354
03355 }
03356 rem = FITS_CARDSIZE - 8;
03357 while (rlen--) {
03358 if ((c = *(str++)) == '\n') {
03359 if (rem < (FITS_CARDSIZE - 8)) {
03360 while (rem) {
03361 fputc (sp, fp);
03362 rem--;
03363 }
03364 }
03365 } else {
03366 fputc (c, fp);
03367 rem--;
03368 }
03369 if (rem == 0 && rlen && *str != '\n') {
03370 numput++;
03371 if (fwrite ("HISTORY ", 8, 1, fp) != 1) {
03372 ;
03373
03374
03375
03376
03377 }
03378 rem = FITS_CARDSIZE - 8;
03379 }
03380 }
03381 while (rem--)
03382 fputc (sp, fp);
03383 }
03384
03385 return numput;
03386 }
03387
03388 static int PutRemainBlanks (int n, FILE *fp) {
03389 int remain, written;
03390 int len = 0;
03391
03392 written = n % FITS_NCARDS;
03393 remain = FITS_NCARDS - written;
03394 if (remain % FITS_NCARDS) {
03395 len = (FITS_CARDSIZE * (FITS_NCARDS - written));
03396 fprintf (fp, "%*c", len, ' ');
03397 }
03398 return len;
03399 }
03400
03401 static int write_fits_head (DR *dr, FILE *fp) {
03402 int status = NO_ERROR;
03403 int cards = 0;
03404
03405 cards += PutMandatory (dr, fp);
03406
03407
03408
03409 cards += PutCommentary (dr, fp);
03410 cards += PutAttributes (dr, fp);
03411 cards += PutOneMandatory ("END", NULL, DR_VOID, NULL, fp);
03412 PutRemainBlanks (cards, fp);
03413
03414 return status;
03415 }
03416
03417 static int write_fits_data (DR *dr, FILE *fp) {
03418 int status = NO_ERROR;
03419 long nbytes, len;
03420 long mapsize = FITS_NCARDS * FITS_CARDSIZE;
03421 char *zero;
03422
03423 nbytes = dr_data_length (dr);
03424 if (nbytes == 0 || dr->data == NULL) return status;
03425 nbytes *= dr->datumsize;
03426
03427 #ifdef IEEE_EL
03428 dr_flip_data (dr);
03429 #endif
03430 if (fwrite (dr->data, 1, nbytes, fp) != nbytes) {
03431
03432
03433
03434
03435 status = WRITE_FAILURE;
03436 }
03437
03438 #ifdef IEEE_EL
03439 dr_flip_data (dr);
03440 #endif
03441
03442 len = (nbytes) % mapsize;
03443 if (len) {
03444 len = mapsize - len;
03445 if (!(zero = (char *) calloc (1, len)))
03446 return MALLOC_FAILURE;
03447 if (fwrite (zero, 1, len, fp) != len) {
03448
03449
03450
03451 status = WRITE_FAILURE;
03452 }
03453 free (zero);
03454 }
03455 return (status);
03456 }
03457
03458 int dr_write_fits (DR *dr, FILE *out) {
03459 double scale, bias;
03460 unsigned long clngth;
03461 int status = NO_ERROR, save_status = NO_ERROR;
03462 int bpp, datatype, savetype, reconvert = 0, rescale = 0;
03463 unsigned char *old, *new, *new0 = NULL;
03464 if (!dr) return DR_POINTER_NULL;
03465 if (dr_data_length (dr) == 0) {
03466
03467 if (status = write_fits_head (dr, out)) {
03468 if (status != DR_INVALID_DATATYPE || dr_data_length (dr)) {
03469
03470
03471
03472 return status;
03473 }
03474 }
03475 return status;
03476 }
03477
03478 savetype = datatype = dr_datatype (dr);
03479 if (bpp = dr->scaling) {
03480 bpp = (bpp < 9) ? 8 : (bpp < 17) ? 16 : 32;
03481 scale = dr_bscale (dr);
03482 bias = dr_bzero (dr);
03483 if (datatype == DR_FLOAT || datatype == DR_DOUBLE) {
03484
03485 clngth = dr_numbytes (dr) * dr_data_length (dr);
03486 new = new0 = (unsigned char *)malloc (clngth);
03487 old = (unsigned char *)dr_data (dr);
03488 while (clngth--) *new++ = *old++;
03489 if (scale != 1.0 || bias != 0.0)
03490 dr_scale_data (dr, (1.0 / scale), -(bias / scale));
03491 datatype = (bpp == 8) ? DR_BYTE : (bpp == 16) ? DR_SHORT : DR_INT;
03492 if (save_status = dr_data_convert (dr, datatype)) ;
03493
03494
03495
03496
03497
03498
03499
03500 dr_set_scaling (dr, bpp, scale, bias);
03501 reconvert = 1;
03502 } else {
03503 dr_set_scaling (dr, 0, 1.0, 0.0);
03504 rescale = 1;
03505 }
03506 }
03507
03508
03509
03510
03511
03512
03513
03514
03515
03516
03517
03518
03519
03520
03521
03522
03523
03524
03525 if (status = write_fits_head (dr, out)) {
03526 if (status != DR_INVALID_DATATYPE || dr_data_length (dr)) {
03527
03528
03529
03530 return status;
03531 }
03532 }
03533 if (status = write_fits_data (dr, out)) {
03534
03535
03536
03537 return status;
03538 }
03539
03540 if (reconvert) {
03541 dr_free_data (dr);
03542 dr_set_datatype (dr, savetype);
03543 dr_set_data (dr, new0);
03544 }
03545 if (rescale)
03546 dr_set_scaling (dr, bpp, scale, bias);
03547 if (status != NO_ERROR) return status;
03548 return save_status;
03549 }
03550
03551
03552
03553
03554
03555 #define MAXCOLORS (256)
03556
03557 int getColorTable (char *name, int *bpp, int *Red, int *Green, int *Blue) {
03558 FILE *ctbl;
03559 int z;
03560
03561 if (!(ctbl = fopen (name, "r"))) return 0;
03562 fscanf (ctbl, "%d", bpp);
03563 for (z=0; z<MAXCOLORS; z++) {
03564 if (fscanf (ctbl, "%d %d %d", Red+z, Green+z, Blue+z) != 3) {
03565 fclose (ctbl);
03566 return z;
03567 }
03568 }
03569 fclose (ctbl);
03570 return z;
03571 }
03572
03573
03574
03575
03576
03577
03578
03579 typedef struct _nmval {
03580 char *name;
03581 double value;
03582 } NameVal_t;
03583
03584 static NameVal_t pre[] = {
03585 "exa", 1e18,
03586 "pecta", 1e15,
03587 "tera", 1e12,
03588 "giga", 1e9,
03589 "mega", 1e6,
03590 "kilo", 1e3,
03591 "hecto", 1e2,
03592 "deca", 1e1,
03593 "deci", 1e-1,
03594 "centi", 1e-2,
03595 "milli", 1e-3,
03596 "micro", 1e-6,
03597 "mu", 1e-6,
03598 "nano", 1e-9,
03599 "pico", 1e-12,
03600 "femto", 1e-15,
03601 "atto", 1e-18,
03602 };
03603
03604 #if 0
03605 already defined in libmisc.a
03606
03607 char *mprefix(char *str, double *mult)
03608 {
03609 int i;
03610 char *pc;
03611 char *s = str;
03612 int n_prefixes = sizeof(pre)/sizeof(NameVal_t);
03613
03614
03615 for (i=0; i < n_prefixes; ++i)
03616 if (pc = strstr(s, pre[i].name))
03617 {
03618 s = pc + strlen(pre[i].name);
03619 *mult = pre[i].value;
03620 return(s);
03621 }
03622 *mult = 1.0;
03623 return(str);
03624 }
03625 #endif
03626
03627
03628
03629
03630
03631
03632
03633
03634 typedef struct
03635 {
03636 char *nm;
03637 int code;
03638 } nametable;
03639
03640 static nametable tmunit[] = {
03641 "hz", 8,
03642 "hertz", 8,
03643 "rot", 7,
03644 "rots", 7,
03645 "rotation", 7,
03646 "rotations", 7,
03647 "deg", 6,
03648 "degs", 6,
03649 "degree", 6,
03650 "degrees", 6,
03651 "wk", 5,
03652 "wks", 5,
03653 "week", 5,
03654 "weeks", 5,
03655 "w", 5,
03656 "d", 4,
03657 "day", 4,
03658 "days", 4,
03659 "h", 3,
03660 "hr", 3,
03661 "hrs", 3,
03662 "hour", 3,
03663 "hours", 3,
03664 "m", 2,
03665 "min", 2,
03666 "mins", 2,
03667 "minute", 2,
03668 "minutes", 2,
03669 "secs", 1,
03670 "second", 1,
03671 "seconds", 1,
03672 "s", 1,
03673 "", 0,
03674 0, 0,
03675 };
03676
03677
03678
03679
03680
03681
03682
03683
03684
03685
03686
03687
03688
03689
03690
03691
03692
03693
03694
03695
03696
03697
03698
03699
03700
03701 static int lookup(char *n, nametable *t)
03702 {
03703 while (strcasecmp(n,t->nm) && t->code) ++t;
03704 return(t->code);
03705 }
03706
03707 #if 0
03708 already defined in libmisc.a
03709
03710 TIME atoinc(char *str)
03711 {
03712 double num, mult;
03713 char *units, *base_units;
03714
03715 if (!str) return 0;
03716 num = strtod (str, &units);
03717 if (str == units) num = 1;
03718 if (*units == '_') units++;
03719
03720 base_units = mprefix(units, &mult);
03721 if (*base_units == '_') base_units++;
03722
03723 switch(lookup(base_units,tmunit))
03724 {
03725 case 1:
03726 return(mult*num);
03727 case 2:
03728 return(mult*num*60.0);
03729 case 3:
03730 return(mult*num*3600.0);
03731 case 4:
03732 return(mult*num*86400);
03733 case 5:
03734 return(num*604800);
03735 case 6:
03736 return(num);
03737 case 7:
03738 return(num*360);
03739 case 8:
03740 return(mult*num);
03741 default:
03742 return(0);
03743 }
03744 }
03745 #endif
03746
03747 #define integral(x) ((x)==(long)(x))
03748
03749 #if 0
03750 already defined in libmisc.a
03751
03752 char *sprint_inc(char *str, TIME inc)
03753 {
03754 double ii;
03755
03756 if (integral(ii = inc/31556952)) sprintf(str,"%.0fyear",ii);
03757 else if (integral(ii = inc/604800)) sprintf(str,"%.0fweek",ii);
03758 else if (integral(ii = inc/86400)) sprintf(str,"%.0fday",ii);
03759 else if (integral(ii = inc/3600)) sprintf(str,"%.0fhour",ii);
03760 else if (integral(ii = inc/60)) sprintf(str,"%.0fminute",ii);
03761 else sprintf(str,"%.fsecond",ii=inc);
03762 if (ii>1 || ii<-1) strcat(str,"s");
03763 return(str);
03764 }
03765
03766 int fprint_inc(FILE *fp, TIME inc)
03767 {
03768 char str[64];
03769 return(fprintf(fp,"%s",sprint_inc(str,inc)));
03770 }
03771
03772 int print_inc(inc)
03773 TIME inc;
03774 {
03775 return(fprint_inc(stdout,inc));
03776 }
03777 #endif
03778
03779
03780
03781
03782
03783
03784
03785
03786
03787
03788
03789
03790
03791
03792
03793
03794
03795
03796
03797
03798
03799
03800
03801
03802
03803
03804
03805
03806
03807
03808
03809
03810
03811
03812
03813
03814
03815
03816
03817
03818
03819
03820
03821
03822
03823
03824
03825
03826
03827
03828
03829
03830
03831
03832
03833
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
03847
03848
03849
03850
03851
03852
03853
03854
03855
03856
03857
03858
03859
03860
03861
03862
03863
03864
03865
03866 char *dr_getkey_str(DR *dr, char *key)
03867 {
03868 char *c = dr_search_attrvalue_str(dr,key);
03869 if (c)
03870 return(c);
03871 return(strdup(""));
03872 }
03873
03874
03875 char *DR_getkey_str(DR *dr, char *key)
03876 {
03877 static char tmp[DR_MAXSTRING];
03878 char *c;
03879 strcpy(tmp, (c=dr_getkey_str(dr,key)));
03880 free(c);
03881 return(tmp);
03882 }
03883
03884 double dr_getkey_double(DR *dr, char *key)
03885 {
03886 return(dr_search_attrvalue_double(dr,key));
03887 }
03888
03889 int dr_getkey_int(DR *dr, char *key)
03890 {
03891 double dv = dr_search_attrvalue_double(dr,key);
03892 int retval;
03893 if (is_D_MISSING(dv))
03894 retval = I_MISSING;
03895 else
03896 retval = dv + (dv >= 0.0 ? 0.5 : -0.5);
03897 return(retval);
03898 }
03899
03900 TIME dr_getkey_time(DR *dr, char *key)
03901 {
03902 TIME retval;
03903 char *tim = dr_getkey_str(dr,key);
03904 if (*tim == '\0')
03905 retval = T_MISSING;
03906 else
03907 retval = sscan_time(tim);
03908 free(tim);
03909 return(retval);
03910 }
03911
03912 TIME dr_getkey_time_interval(DR *dr, char *key)
03913 {
03914 return(atoinc(DR_getkey_str(dr,key)));
03915 }
03916
03917
03918
03919 int dr_setkey_str(DR *dr, char *key, char *str)
03920 {
03921 int stat=dr_set_attribute(dr, key, str, DR_STRING, NULL);
03922 if (stat)
03923 fprintf(stderr,"*** WARNING dr_set_attribute failed, ptr=%p, key=%s\n", dr, key);
03924 return(stat);
03925 }
03926
03927 int dr_setkey_int(DR *dr, char *key, int val)
03928 {
03929 int tmp = val;
03930 int stat=dr_set_attribute(dr, key, &tmp, DR_INT, NULL);
03931 if (stat)
03932 fprintf(stderr,"*** WARNING dr_set_attribute failed, ptr=%p, key=%s\n", dr, key);
03933 return(stat);
03934 }
03935
03936 int dr_setkey_double(DR *dr, char *key, double val)
03937 {
03938 double tmp = val;
03939 int stat=dr_set_attribute(dr, key, &tmp, DR_DOUBLE, NULL);
03940 if (stat)
03941 fprintf(stderr,"*** WARNING dr_set_attribute failed, ptr=%p, key=%s\n", dr, key);
03942 return(stat);
03943 }
03944
03945 int dr_setkey_time(DR *dr, char *key, TIME time)
03946 {
03947 char tmp[DR_MAXSTRING];
03948 if (time == T_MISSING)
03949 tmp[0] = '\0';
03950 else
03951 sprint_ut(tmp,time);
03952 return(dr_setkey_str(dr, key, tmp));
03953 }
03954
03955 int dr_setkey_time_interval(DR *dr, char *key, TIME time)
03956 {
03957 char tmp[DR_MAXSTRING];
03958 sprint_inc(tmp,time);
03959 return(dr_setkey_str(dr, key, tmp));
03960 }
03961
03962 int dr_put_fits(DR *dr, char*file)
03963 {
03964 FILE *fp;
03965 int status;
03966 if (!dr)
03967 return(DR_POINTER_NULL);
03968 fp = fopen(file, "w");
03969 if (!fp)
03970 return(FILE_POINTER_NULL);
03971 status = dr_write_fits(dr, fp);
03972 fclose(fp);
03973 return(status);
03974 }
03975
03976
03977 DR *dr_get_fits(char *filename)
03978 {
03979 int status;
03980 FILE *fp;
03981 DR *fits;
03982 fp = fopen(filename, "r");
03983 if (!fp)
03984 {
03985 fprintf(stderr,"Failed to open fits file %s\n",filename);
03986 fclose(fp);
03987 return(NULL);
03988 }
03989 fits = dr_read_fits(fp, &status);
03990 if (!fits || status)
03991 {
03992 if (fits)
03993 dr_free(&fits);
03994 fprintf(stderr,"Failed to find fits file in %s\n",filename);
03995 fclose(fp);
03996 return(NULL);
03997 }
03998 fclose(fp);
03999 return(fits);
04000 }
04001
04002
04003 DR *dr_get_fits_head(char *filename)
04004 {
04005 int status;
04006 FILE *fp;
04007 DR *fits;
04008 fp = fopen(filename, "r");
04009 if (!fp)
04010 {
04011 fprintf(stderr,"Failed to open fits file %s\n",filename);
04012 return(NULL);
04013 }
04014 fits = dr_read_fits_header(fp, &status);
04015 if (!fits || status)
04016 {
04017 if (fits)
04018 dr_free(&fits);
04019 fprintf(stderr,"Failed to find fits header in %s\n",filename);
04020 fclose(fp);
04021 return(NULL);
04022 }
04023 fclose(fp);
04024 return(fits);
04025 }
04026
04027
04028 void dr_print_header(DR *dr)
04029 {
04030 ATTRIBUTES *attr;
04031 if (!dr)
04032 fprintf(stderr,"$$$ dr_print_header - dr is NULL, return.\n");
04033 else
04034 for (attr = dr->attrib; attr; attr = attr->next)
04035 fprintf(stderr,"%s = %s\n",attr->name, dr_attrvalue_str(attr));
04036 }
04037
04038 int dr_setkey_drmstype(DR *dr, char *name, DRMS_Keyword_t *key)
04039 {
04040 if (!dr || !key)
04041 return(1);
04042 switch (key->info->type)
04043 {
04044 case DRMS_TYPE_CHAR:
04045 dr_setkey_int(dr, name, key->value.char_val);
04046 break;
04047 case DRMS_TYPE_SHORT:
04048 dr_setkey_int(dr, name, key->value.short_val);
04049 break;
04050 case DRMS_TYPE_INT:
04051 dr_setkey_int(dr, name, key->value.int_val);
04052 break;
04053 case DRMS_TYPE_LONGLONG:
04054 dr_setkey_int(dr, name, (int)key->value.longlong_val);
04055 break;
04056 case DRMS_TYPE_FLOAT:
04057 dr_setkey_double(dr, name, key->value.float_val);
04058 break;
04059 case DRMS_TYPE_DOUBLE:
04060 dr_setkey_double(dr, name, key->value.double_val);
04061 break;
04062 case DRMS_TYPE_TIME:
04063 dr_setkey_time(dr, name, key->value.time_val);
04064 break;
04065 case DRMS_TYPE_STRING:
04066 dr_setkey_str(dr, name, key->value.string_val);
04067 }
04068 return(0);
04069 }
04070
04071
04072 int drms2drtype(DRMS_Type_t type)
04073 {
04074 switch(type)
04075 {
04076 case DRMS_TYPE_CHAR:
04077 return DR_BYTE;
04078 break;
04079 case DRMS_TYPE_SHORT:
04080 return DR_SHORT;
04081 break;
04082 case DRMS_TYPE_INT:
04083 return DR_INT;
04084 break;
04085 case DRMS_TYPE_LONGLONG:
04086 return DR_LONG;
04087 break;
04088 case DRMS_TYPE_FLOAT:
04089 return DR_FLOAT;
04090 break;
04091 case DRMS_TYPE_DOUBLE:
04092 return DR_DOUBLE;
04093 break;
04094 case DRMS_TYPE_TIME:
04095 return DR_TIME;
04096 break;
04097 case DRMS_TYPE_STRING:
04098 return DR_STRING;
04099 default:
04100 fprintf(stderr, "ERROR: Unhandled DRMS type %d\n",(int)type);
04101 XASSERT(0);
04102 return DR_STRING;
04103 break;
04104 }
04105 }
04106
04107
04108 DRMS_Type_t dr2drmstype(int type)
04109 {
04110 switch(type)
04111 {
04112 case DR_BYTE:
04113 return DRMS_TYPE_CHAR;
04114 break;
04115 case DR_SHORT:
04116 return DRMS_TYPE_SHORT;
04117 break;
04118 case DR_INT:
04119 return DRMS_TYPE_INT;
04120 break;
04121 case DR_LONG:
04122 return DRMS_TYPE_LONGLONG;
04123 break;
04124 case DR_FLOAT:
04125 return DRMS_TYPE_FLOAT;
04126 break;
04127 case DR_DOUBLE:
04128 return DRMS_TYPE_DOUBLE;
04129 break;
04130 case DR_TIME:
04131 return DRMS_TYPE_TIME;
04132 break;
04133 case DR_STRING:
04134 return DRMS_TYPE_STRING;
04135 default:
04136 fprintf(stderr, "ERROR: Unhandled DR type %d\n",type);
04137 XASSERT(0);
04138 return DRMS_TYPE_STRING;
04139 break;
04140 }
04141 }
04142
04143
04144
04145
04146
04147 int drms_segment_write_FITS_from_file(DRMS_Segment_t *seg, char *infile)
04148 {
04149 int status;
04150 int naxis, iaxis;
04151 DRMS_Protocol_t proto_want;
04152 DR *header;
04153 int want_data_type;
04154
04155
04156 header = dr_get_fits_head(infile);
04157 if (!header)
04158 return(DRMS_ERROR_IOERROR);
04159 want_data_type = drms2drtype(seg->info->type);
04160 if (header->datatype != want_data_type)
04161 {
04162 fprintf(stderr,"Write FITS from file: type miss-match, have=%d, jsd says %d\n",header->datatype,want_data_type);
04163 dr_free(&header);
04164 return(FITS_ERROR);
04165 }
04166 naxis = header->rank;
04167 if (naxis != seg->info->naxis)
04168 {
04169 fprintf(stderr,"Write FITS from file: naxis miss-match, have=%d, jsd says %d\n",naxis,seg->info->naxis);
04170 dr_free(&header);
04171 return(FITS_ERROR);
04172 }
04173 for (iaxis=0; iaxis < naxis; iaxis++)
04174 {
04175 int dim;
04176 dim = header->length[iaxis];
04177 if (seg->info->scope == DRMS_VARDIM)
04178 seg->axis[iaxis] = dim;
04179 else
04180 {
04181 if (dim != seg->axis[iaxis])
04182 {
04183 fprintf(stderr,"Write FITS from file: dimension error, have=%d, jsd says %d\n",dim,seg->axis[iaxis]);
04184 dr_free(&header);
04185 return(FITS_ERROR);
04186 }
04187 }
04188 }
04189 dr_free(&header);
04190
04191
04192 proto_want = seg->info->protocol;
04193 seg->info->protocol = DRMS_GENERIC;
04194 status = drms_segment_write_from_file(seg, infile);
04195 seg->info->protocol = proto_want;
04196 return(status);
04197
04198
04199 }
04200
04201 int dr_write_fits_to_drms_segment(DR *dr, char *fitsname, DRMS_Record_t *rec, int segno)
04202 {
04203 DRMS_Segment_t *seg = drms_segment_lookupnum(rec,segno);
04204 FILE *fp;
04205 char path[1024];
04206 DR *header;
04207 int status;
04208 int naxis, iaxis;
04209 int want_data_type;
04210
04211
04212 fp = drms_record_fopen(rec, fitsname, "w");
04213 status = dr_write_fits(dr, fp);
04214 if (status)
04215 {
04216 fprintf(stderr, "Failed to write fits file to segment, status = %d\n", status);
04217 return(FITS_ERROR);
04218 }
04219 fclose(fp);
04220 CHECKSNPRINTF(snprintf(seg->filename, DRMS_MAXSEGFILENAME, "%s", fitsname), DRMS_MAXSEGFILENAME);
04221
04222
04223 drms_record_directory(rec, path, 1);
04224 strcat(path, "/");
04225 strcat(path, fitsname);
04226 header = dr_get_fits_head(path);
04227 if (!header)
04228 return(DRMS_ERROR_IOERROR);
04229 want_data_type = drms2drtype(seg->info->type);
04230 if (header->datatype != want_data_type)
04231 {
04232 fprintf(stderr,"Write FITS to segment: type miss-match, dr says %d, jsd says %d\n",header->datatype,want_data_type);
04233 return(FITS_ERROR);
04234 }
04235 naxis = header->rank;
04236 if (naxis != seg->info->naxis)
04237 {
04238 fprintf(stderr,"Write FITS to segment: naxis miss-match, dr says %d, jsd says %d\n",naxis,seg->info->naxis);
04239 return(FITS_ERROR);
04240 }
04241 for (iaxis=0; iaxis < naxis; iaxis++)
04242 {
04243 int dim;
04244 dim = header->length[iaxis];
04245 if (seg->info->scope == DRMS_VARDIM)
04246 seg->axis[iaxis] = dim;
04247 else
04248 {
04249 if (dim != seg->axis[iaxis])
04250 {
04251 fprintf(stderr,"Write FITS to segment: dimension error, dr says %d, jsd says %d\n",dim,seg->axis[iaxis]);
04252 return(FITS_ERROR);
04253 }
04254 }
04255 }
04256 return(0);
04257 }
04258