26 #include <wx/wxprec.h>
30 #include <wx/datetime.h>
31 #include <wx/hashmap.h>
40 #include "model/georef.h"
41 #include "model/logger.h"
49 time_t s_next_epoch = TIDE_BAD_TIME;
50 time_t s_this_epoch = TIDE_BAD_TIME;
53 double time2dt_tide(time_t t,
int deriv,
IDX_entry *pIDX);
54 int yearoftimet(time_t t);
55 void happy_new_year(
IDX_entry *pIDX,
int new_year);
56 void set_epoch(
IDX_entry *pIDX,
int year);
58 double time2tide(time_t t,
IDX_entry *pIDX) {
return time2dt_tide(t, 0, pIDX); }
64 double BOGUS_amplitude(
double mpy,
IDX_entry *pIDX) {
67 if (!pmsd->have_BOGUS)
68 return (mpy * pIDX->max_amplitude);
71 return (sqrt(mpy * pIDX->max_amplitude));
73 return (-sqrt(-mpy * pIDX->max_amplitude));
78 double time2atide(time_t t,
IDX_entry *pIDX) {
79 return BOGUS_amplitude(time2tide(t, pIDX), pIDX) + pIDX->pref_sta_data->DATUM;
90 int next_big_event(time_t *tm,
IDX_entry *pIDX) {
92 int flags = 0, slope = 0;
93 p = time2atide(*tm, pIDX);
95 q = time2atide(*tm, pIDX);
99 if ((slope == 1 && q < p) || (slope == 0 && p < q)) {
101 flags |= (1 << slope);
115 if ((p > marklev && q <= marklev) || (p < marklev && q >= marklev)) {
131 q = time2atide(*tm, pIDX);
132 if ((slope == 1 && q < p) || (slope == 0 && p < q)) {
134 flags |= (1 << slope);
146 if (flags < 4) *tm -= 60;
150 q = time2atide(*tm, pIDX);
159 double time2mean(time_t t,
IDX_entry *pIDX) {
162 int new_year = yearoftimet(t);
163 if (pIDX->epoch_year != new_year) happy_new_year(pIDX, new_year);
165 for (a = 0; a < pIDX->num_csts; a++) {
166 if (pIDX->m_cst_speeds[a] < 6e-6) {
167 tide += pIDX->m_work_buffer[a] *
168 cos(pIDX->m_cst_speeds[a] * ((
long)(t - pIDX->epoch) +
169 pIDX->pref_sta_data->meridian) +
170 pIDX->m_cst_epochs[a][pIDX->epoch_year - pIDX->first_year] -
171 pIDX->pref_sta_data->epoch[a]);
182 double time2asecondary(time_t t,
IDX_entry *pIDX) {
183 time_t tadj = t + pIDX->station_tz_offset;
186 if (!(pIDX->have_offsets))
return time2atide(tadj, pIDX);
193 #define intervalwidth 15
194 #define stretchfactor 3
196 static time_t lowtime = 0, hightime = 0;
197 static double lowlvl, highlvl;
199 double S, Z, HI, HS, magicnum;
200 time_t interval = 3600 * intervalwidth;
201 long difflow, diffhigh;
202 int badlowflag = 0, badhighflag = 0;
209 T = tadj - (pIDX->IDX_ht_time_off * 60 + pIDX->IDX_lt_time_off * 60) / 2;
217 Z = time2mean(T, pIDX);
218 S = time2tide(T, pIDX) - Z;
240 difflow = T - lowtime;
242 difflow = lowtime - T;
244 diffhigh = T - hightime;
246 diffhigh = hightime - T;
249 if (difflow > interval * stretchfactor) badlowflag = 1;
250 if (badlowflag || (difflow > interval && S > 0)) {
254 next_big_event(&tt, pIDX);
255 lowlvl = time2tide(tt, pIDX);
257 while (tt < T + interval) {
258 next_big_event(&tt, pIDX);
259 tl = time2tide(tt, pIDX);
260 if (tl < lowlvl && tt < T + interval) {
267 if (diffhigh > interval * stretchfactor) badhighflag = 1;
268 if (badhighflag || (diffhigh > interval && S < 0)) {
272 next_big_event(&tt, pIDX);
273 highlvl = time2tide(tt, pIDX);
275 while (tt < T + interval) {
276 next_big_event(&tt, pIDX);
277 tl = time2tide(tt, pIDX);
278 if (tl > highlvl && tt < T + interval) {
298 magicnum = 0.5 * S / fabs(highlvl - Z);
300 magicnum = 0.5 * S / fabs(lowlvl - Z);
302 T = T - (time_t)(magicnum * ((pIDX->IDX_ht_time_off * 60) -
303 (pIDX->IDX_lt_time_off * 60)));
304 HI = time2tide(T, pIDX);
307 double ht_off, lt_off;
308 if (pIDX->pref_sta_data->have_BOGUS) {
309 ht_off = pIDX->IDX_ht_off *
311 lt_off = pIDX->IDX_lt_off * pIDX->IDX_lt_off;
313 ht_off = pIDX->IDX_ht_off;
314 lt_off = pIDX->IDX_lt_off;
318 HI = BOGUS_amplitude(HI, pIDX) + pIDX->pref_sta_data->DATUM;
320 double RH = 1.0, RL = 1.0, HH = 0.0, HL = 0.0;
321 RH = pIDX->IDX_ht_mpy;
323 RL = pIDX->IDX_lt_mpy;
329 HS = HI * ((RH + RL) / 2 + (RH - RL) * magicnum) + (HH + HL) / 2 +
330 (HH - HL) * magicnum;
384 double _time2dt_tide(time_t t,
int deriv,
IDX_entry *pIDX) {
385 double dt_tide = 0.0;
389 tempd = M_PI / 2.0 * deriv;
390 for (a = 0; a < pIDX->num_csts; a++) {
391 term = pIDX->m_work_buffer[a] *
393 pIDX->m_cst_speeds[a] *
394 ((
long)(t - pIDX->epoch) + pIDX->pref_sta_data->meridian) +
395 pIDX->m_cst_epochs[a][pIDX->epoch_year - pIDX->first_year] -
396 pIDX->pref_sta_data->epoch[a]);
397 for (b = deriv; b > 0; b--) term *= pIDX->m_cst_speeds[a];
420 static double blend_weight(
double x,
int deriv) {
423 if (x2 >= 1.0)
return deriv == 0 && x > 0.0 ? 1.0 : 0.0;
427 return ((3.0 * x2 - 10.0) * x2 + 15.0) * x / 16.0 + 0.5;
429 return ((x2 - 2.0) * x2 + 1.0) * (15.0 / 16.0);
431 return (x2 - 1.0) * x * (15.0 / 4.0);
440 double blend_tide(time_t t,
unsigned int deriv,
int first_year,
double blend,
442 double fl[TIDE_MAX_DERIV + 1];
443 double fr[TIDE_MAX_DERIV + 1];
445 double w[TIDE_MAX_DERIV + 1];
454 int year = yearoftimet(t);
455 if (year == first_year + 1)
457 else if (year != first_year)
458 happy_new_year(pIDX, first_year);
459 for (n = 0; n <= deriv; n++) fp[n] = _time2dt_tide(t, n, pIDX);
466 happy_new_year(pIDX, first_year + 1);
469 happy_new_year(pIDX, first_year);
472 for (n = 0; n <= deriv; n++) {
473 fp[n] = _time2dt_tide(t, n, pIDX);
474 w[n] = blend_weight(blend, n);
482 for (n = 0; n <= deriv; n++) {
483 f += fact * w[n] * (fr[deriv - n] - fl[deriv - n]);
484 fact *= (double)(deriv - n) / (n + 1) * (1.0 / TIDE_BLEND_TIME);
486 printf(
" %ld %g %g %g %g\n", (
long)t, blend, fr[0], fl[0], f);
490 double time2dt_tide(time_t t,
int deriv,
IDX_entry *pIDX) {
492 int yott = yearoftimet(t);
496 if (new_year != s_this_year) {
497 if (new_year + 1 < pIDX->first_year + pIDX->num_epochs) {
498 set_epoch(pIDX, new_year + 1);
499 s_next_epoch = pIDX->epoch;
501 s_next_epoch = TIDE_BAD_TIME;
503 happy_new_year(pIDX, s_this_year = new_year);
504 s_this_epoch = pIDX->epoch;
511 if (t - s_this_epoch <= TIDE_BLEND_TIME && s_this_year > pIDX->first_year)
512 return blend_tide(t, deriv, s_this_year - 1,
513 (
double)(t - s_this_epoch) / TIDE_BLEND_TIME, pIDX);
514 else if (s_next_epoch - t <= TIDE_BLEND_TIME &&
515 s_this_year + 1 < pIDX->first_year + pIDX->num_epochs)
516 return blend_tide(t, deriv, s_this_year,
517 -(
double)(s_next_epoch - t) / TIDE_BLEND_TIME, pIDX);
522 if (pIDX->epoch_year != new_year) happy_new_year(pIDX, new_year);
524 return _time2dt_tide(t, deriv, pIDX);
529 void figure_max_amplitude(
IDX_entry *pIDX) {
532 if (pIDX->max_amplitude == 0.0) {
533 for (i = 0; i < pIDX->num_nodes; i++) {
534 double year_amp = 0.0;
536 for (a = 0; a < pIDX->num_csts; a++)
537 year_amp += pIDX->pref_sta_data->amplitude[a] * pIDX->m_cst_nodes[a][i];
538 if (year_amp > pIDX->max_amplitude) pIDX->max_amplitude = year_amp;
544 void figure_multipliers(
IDX_entry *pIDX,
int year) {
547 figure_max_amplitude(pIDX);
548 for (a = 0; a < pIDX->num_csts; a++) {
549 pIDX->m_work_buffer[a] = pIDX->pref_sta_data->amplitude[a] *
550 pIDX->m_cst_nodes[a][year - pIDX->first_year] /
556 #define compare_int(a, b) (((int)(a)) - ((int)(b)))
557 int compare_tm(
struct tm *a,
struct tm *b) {
565 temp = compare_int(a->tm_year, b->tm_year);
566 if (temp)
return temp;
567 temp = compare_int(a->tm_mon, b->tm_mon);
568 if (temp)
return temp;
569 temp = compare_int(a->tm_mday, b->tm_mday);
570 if (temp)
return temp;
571 temp = compare_int(a->tm_hour, b->tm_hour);
572 if (temp)
return temp;
573 temp = compare_int(a->tm_min, b->tm_min);
574 if (temp)
return temp;
575 return compare_int(a->tm_sec, b->tm_sec);
581 time_t tm2gmt(
struct tm *ht) {
582 time_t guess, newguess, thebit;
583 int loopcounter, compare;
587 loopcounter = (
sizeof(time_t) * 8) - 1;
588 thebit = ((time_t)1) << (loopcounter - 1);
593 if ((
signed long)thebit < (time_t)(0)) {
596 thebit = ((time_t)1) << (loopcounter - 1);
599 for (; loopcounter; loopcounter--) {
600 newguess = guess | thebit;
601 gt = gmtime(&newguess);
603 compare = compare_tm(gt, ht);
604 if (compare <= 0) guess = newguess;
612 int yearoftimet(time_t t) {
return ((gmtime(&t))->tm_year) + 1900; }
615 void set_epoch(
IDX_entry *pIDX,
int year) {
618 ht.tm_year = year - 1900;
619 ht.tm_sec = ht.tm_min = ht.tm_hour = ht.tm_mon = 0;
621 pIDX->epoch = tm2gmt(&ht);
625 void happy_new_year(
IDX_entry *pIDX,
int new_year) {
626 pIDX->epoch_year = new_year;
627 figure_multipliers(pIDX, new_year);
628 set_epoch(pIDX, new_year);
634 TCMgr::~TCMgr() { PurgeData(); }
636 void TCMgr::PurgeData() {
637 m_Combined_IDX_array.clear();
640 m_source_array.Clear();
643 TC_Error_Code TCMgr::LoadDataSources(std::vector<std::string> &sources) {
647 m_sourcefile_array.clear();
648 m_sourcefile_array = sources;
652 for (
auto src : sources) {
654 TC_Error_Code r = s->LoadData(src);
655 if (r != TC_NO_ERROR) {
657 msg.Printf(_T(
" Error loading Tide/Currect data source %s "),
659 if (r == TC_FILE_NOT_FOUND)
660 msg += _T(
"Error Code: TC_FILE_NOT_FOUND");
663 msg1.Printf(_T(
"Error code: %d"), r);
669 m_source_array.Add(s);
671 for (
int k = 0; k < s->GetMaxIndex(); k++) {
673 pIDX->IDX_rec_num = num_IDX;
675 m_Combined_IDX_array.push_back(pIDX);
682 if (m_Combined_IDX_array.empty())
684 NULL, _(
"It seems you have no tide/current harmonic data installed."),
685 _(
"OpenCPN Info"), wxOK | wxCENTER);
687 ScrubCurrentDepths();
691 void TCMgr::ScrubCurrentDepths() {
696 WX_DECLARE_STRING_HASH_MAP(
int, currentDepth_index_hash);
698 currentDepth_index_hash hash1;
700 for (
int i = 1; i < Get_max_IDX() + 1; i++) {
702 if (a->IDX_type ==
'C') {
703 if (a->current_depth > 0) {
704 int depth_a = a->current_depth;
713 key1.Printf(
"%10.6f %10.6f", a->IDX_lat, a->IDX_lon);
715 currentDepth_index_hash::iterator it = hash1.find(key1);
716 if (it == hash1.end()) {
723 std::string bName(b->IDX_station_name);
724 int depth_b = b->current_depth;
725 if (depth_a < depth_b) {
727 b->b_skipTooDeep = 1;
729 a->b_skipTooDeep = 1;
737 const IDX_entry *TCMgr::GetIDX_entry(
int index)
const {
738 if ((
unsigned int)index < m_Combined_IDX_array.size())
739 return m_Combined_IDX_array[index];
744 bool TCMgr::GetTideOrCurrent(time_t t,
int idx,
float &tcvalue,
float &dir) {
750 IDX_entry *pIDX = m_Combined_IDX_array[idx];
758 if (!pIDX->IDX_Useable) {
764 if (pIDX->pDataSource) {
765 if (pIDX->pDataSource->LoadHarmonicData(pIDX) != TC_NO_ERROR)
return false;
768 pIDX->max_amplitude = 0.0;
769 int yott = yearoftimet(t);
771 happy_new_year(pIDX, yott);
775 double level = time2asecondary(t + (00 * 60), pIDX);
777 dir = pIDX->IDX_flood_dir;
779 dir = pIDX->IDX_ebb_dir;
786 extern wxDateTime gTimeSource;
788 bool TCMgr::GetTideOrCurrent15(time_t t_d,
int idx,
float &tcvalue,
float &dir,
791 IDX_entry *pIDX = m_Combined_IDX_array[idx];
800 wxDateTime this_now = gTimeSource;
801 if (this_now.IsValid() ==
false) this_now = wxDateTime::Now();
802 wxDateTime this_gmt = this_now.ToGMT();
803 wxTimeSpan diff = this_gmt.Subtract(this_now);
804 int diff_mins = diff.GetMinutes();
806 int station_offset = pIDX->IDX_time_zone;
807 if (this_now.IsDST()) station_offset += 60;
808 int corr_mins = station_offset - diff_mins;
810 wxDateTime today_00 = this_now;
811 today_00.ResetTime();
812 int t_today_00 = today_00.GetTicks();
813 int t_today_00_at_station = t_today_00 - (corr_mins * 60);
816 this_gmt.GetTicks() - (station_offset * 60) + (corr_mins * 60);
818 int t_mins = (t_at_station - t_today_00_at_station) / 60;
819 int t_15s = t_mins / 15;
823 int tref1 = t_today_00_at_station + t_15s * 15 * 60;
824 if (tref1 == pIDX->Valid15) {
825 tcvalue = pIDX->Value15;
830 int tref = t_today_00_at_station + t_15s * 15 * 60;
831 ret = GetTideOrCurrent(tref, idx, tcvalue, dir);
833 pIDX->Valid15 = tref;
834 pIDX->Value15 = tcvalue;
836 pIDX->Ret15 = !(ret == 0);
844 int tref = t_today_00_at_station + t_15s * 15 * 60;
845 ret = GetTideOrCurrent(tref, idx, tcvalue, dir);
847 pIDX->Valid15 = tref;
848 pIDX->Value15 = tcvalue;
850 pIDX->Ret15 = !(ret == 0);
857 bool TCMgr::GetTideFlowSens(time_t t,
int sch_step,
int idx,
float &tcvalue_now,
858 float &tcvalue_prev,
bool &w_t) {
865 IDX_entry *pIDX = m_Combined_IDX_array[idx];
867 if (!pIDX)
return false;
869 if (!pIDX->IDX_Useable)
return false;
871 if (pIDX->pDataSource) {
872 if (pIDX->pDataSource->LoadHarmonicData(pIDX) != TC_NO_ERROR)
return false;
875 pIDX->max_amplitude = 0.0;
876 int yott = yearoftimet(t);
877 happy_new_year(pIDX, yott);
881 tcvalue_now = time2asecondary(t, pIDX);
882 tcvalue_prev = time2asecondary(t + sch_step, pIDX);
885 tcvalue_now > tcvalue_prev;
890 void TCMgr::GetHightOrLowTide(time_t t,
int sch_step_1,
int sch_step_2,
891 float tide_val,
bool w_t,
int idx,
float &tcvalue,
898 IDX_entry *pIDX = m_Combined_IDX_array[idx];
902 if (!pIDX->IDX_Useable)
return;
904 if (pIDX->pDataSource) {
905 if (pIDX->pDataSource->LoadHarmonicData(pIDX) != TC_NO_ERROR)
return;
909 if (abs(t - pIDX->recent_highlow_calc_time) < 60) {
911 tcvalue = pIDX->recent_high_level;
912 tctime = pIDX->recent_high_time;
914 tcvalue = pIDX->recent_low_level;
915 tctime = pIDX->recent_low_time;
920 pIDX->max_amplitude = 0.0;
921 int yott = yearoftimet(t);
922 happy_new_year(pIDX, yott);
925 double newval = tide_val;
926 double oldval = (w_t) ? newval - 1 : newval + 1;
930 while ((newval > oldval) == w_t)
934 ttt = t + (sch_step_1 * j);
935 newval = time2asecondary(ttt, pIDX);
937 oldval = (w_t) ? newval - 1 : newval + 1;
938 while ((newval > oldval) == w_t)
942 ttt = t + (sch_step_1 * j) - (sch_step_2 * k);
943 newval = time2asecondary(ttt, pIDX);
946 tctime = ttt + sch_step_2;
949 pIDX->recent_highlow_calc_time = t;
951 pIDX->recent_high_level = newval;
952 pIDX->recent_high_time = tctime;
954 pIDX->recent_low_level = newval;
955 pIDX->recent_low_time = tctime;
959 int TCMgr::GetStationTimeOffset(
IDX_entry *pIDX) {
return pIDX->IDX_time_zone; }
961 double TCMgr::GetStationLat(
IDX_entry *pIDX) {
return pIDX->IDX_lat; }
963 double TCMgr::GetStationLon(
IDX_entry *pIDX) {
return pIDX->IDX_lon; }
965 int TCMgr::GetNextBigEvent(time_t *tm,
int idx) {
970 int flags = 0, slope = 0;
971 ret = GetTideOrCurrent(*tm, idx, tcvalue[0], dir);
974 ret = GetTideOrCurrent(*tm, idx, tcvalue[0], dir);
977 if (p < q) slope = 1;
979 if ((slope == 1 && q < p) || (slope == 0 && p < q)) {
981 flags |= (1 << slope);
985 if (flags < 4) *tm -= 60;
989 ret = GetTideOrCurrent(*tm, idx, tcvalue[0], dir);
996 std::map<double, const IDX_entry *> TCMgr::GetStationsForLL(
double xlat,
998 std::map<double, const IDX_entry *> x;
1001 for (
int j = 1; j < Get_max_IDX() + 1; j++) {
1002 lpIDX = GetIDX_entry(j);
1003 char type = lpIDX->IDX_type;
1004 wxString locnx(lpIDX->IDX_station_name, wxConvUTF8);
1006 if (type ==
't' || type ==
'T') {
1008 DistanceBearingMercator(xlat, xlon, lpIDX->IDX_lat, lpIDX->IDX_lon, &brg,
1010 x.emplace(std::make_pair(dist, lpIDX));
1017 int TCMgr::GetStationIDXbyName(
const wxString &prefix,
double xlat,
1018 double xlon)
const {
1022 double distx = 100000.;
1024 int jmax = Get_max_IDX();
1026 for (
int j = 1; j < Get_max_IDX() + 1; j++) {
1027 lpIDX = GetIDX_entry(j);
1028 char type = lpIDX->IDX_type;
1029 wxString locnx(lpIDX->IDX_station_name, wxConvUTF8);
1031 if (((type ==
't') || (type ==
'T'))
1032 && (locnx.StartsWith(prefix))) {
1034 DistanceBearingMercator(xlat, xlon, lpIDX->IDX_lat, lpIDX->IDX_lon, &brg,
1046 int TCMgr::GetStationIDXbyNameType(
const wxString &prefix,
double xlat,
1047 double xlon,
char type)
const {
1051 double distx = 100000.;
1055 int jmax = Get_max_IDX();
1057 for (
int j = 1; j < Get_max_IDX() + 1; j++) {
1058 lpIDX = GetIDX_entry(j);
1059 char typep = lpIDX->IDX_type;
1060 wxString locnx(lpIDX->IDX_station_name, wxConvUTF8);
1062 if ((type == typep) && (locnx.StartsWith(prefix))) {
1064 DistanceBearingMercator(xlat, xlon, lpIDX->IDX_lat, lpIDX->IDX_lon, &brg,
1090 #define DEFAULT_HEADER_SIZE 4096
1091 #define DEFAULT_NUMBER_OF_RECORDS 0
1092 #define DEFAULT_LEVEL_UNIT_TYPES 5
1093 #define DEFAULT_DIR_UNIT_TYPES 3
1094 #define DEFAULT_RESTRICTION_TYPES 2
1095 #define DEFAULT_RESTRICTION_BITS 4
1096 #define DEFAULT_TZFILES 406
1097 #define DEFAULT_TZFILE_BITS 10
1098 #define DEFAULT_COUNTRIES 240
1099 #define DEFAULT_COUNTRY_BITS 9
1100 #define DEFAULT_DATUM_TYPES 61
1101 #define DEFAULT_DATUM_BITS 7
1102 #define DEFAULT_LEGALESES 1
1103 #define DEFAULT_LEGALESE_BITS 4
1104 #define DEFAULT_SPEED_SCALE 10000000
1105 #define DEFAULT_EQUILIBRIUM_SCALE 100
1106 #define DEFAULT_NODE_SCALE 10000
1107 #define DEFAULT_AMPLITUDE_BITS 19
1108 #define DEFAULT_AMPLITUDE_SCALE 10000
1109 #define DEFAULT_EPOCH_BITS 16
1110 #define DEFAULT_EPOCH_SCALE 100
1111 #define DEFAULT_RECORD_TYPE_BITS 4
1112 #define DEFAULT_LATITUDE_BITS 25
1113 #define DEFAULT_LATITUDE_SCALE 100000
1114 #define DEFAULT_LONGITUDE_BITS 26
1115 #define DEFAULT_LONGITUDE_SCALE 100000
1116 #define DEFAULT_RECORD_SIZE_BITS 16
1117 #define DEFAULT_STATION_BITS 18
1118 #define DEFAULT_DATUM_OFFSET_BITS 28
1119 #define DEFAULT_DATUM_OFFSET_SCALE 10000
1120 #define DEFAULT_DATE_BITS 27
1121 #define DEFAULT_MONTHS_ON_STATION_BITS 10
1122 #define DEFAULT_CONFIDENCE_VALUE_BITS 4
1123 #define DEFAULT_NUMBER_OF_CONSTITUENTS_BITS 8
1124 #define DEFAULT_TIME_BITS 13
1125 #define DEFAULT_LEVEL_ADD_BITS 17
1126 #define DEFAULT_LEVEL_ADD_SCALE 1000
1127 #define DEFAULT_LEVEL_MULTIPLY_BITS 16
1128 #define DEFAULT_LEVEL_MULTIPLY_SCALE 1000
1129 #define DEFAULT_DIRECTION_BITS 9
1130 #define DEFAULT_CONSTITUENT_SIZE 10
1131 #define DEFAULT_LEVEL_UNIT_SIZE 15
1132 #define DEFAULT_DIR_UNIT_SIZE 15
1133 #define DEFAULT_RESTRICTION_SIZE 30
1134 #define DEFAULT_DATUM_SIZE 70
1135 #define DEFAULT_LEGALESE_SIZE 70
1136 #define DEFAULT_TZFILE_SIZE 30
1137 #define DEFAULT_COUNTRY_SIZE 50
1141 #define INFERRED_SEMI_DIURNAL_COUNT 10
1142 #define INFERRED_DIURNAL_COUNT 10
1145 #pragma warning(disable : 4305)
1148 const NV_CHAR *inferred_semi_diurnal[INFERRED_SEMI_DIURNAL_COUNT] = {
1149 "N2",
"NU2",
"MU2",
"2N2",
"LDA2",
"T2",
"R2",
"L2",
"K2",
"KJ2"};
1150 const NV_CHAR *inferred_diurnal[INFERRED_DIURNAL_COUNT] = {
1151 "OO1",
"M1",
"J1",
"RHO1",
"Q1",
"2Q1",
"P1",
"PI1",
"PHI1",
"PSI1"};
1152 NV_FLOAT32 semi_diurnal_coeff[INFERRED_SEMI_DIURNAL_COUNT] = {
1153 .1759, .0341, .0219, .0235, .0066, .0248, .0035, .0251, .1151, .0064};
1154 NV_FLOAT32 diurnal_coeff[INFERRED_DIURNAL_COUNT] = {
1155 .0163, .0209, .0297, .0142, .0730, .0097, .1755, .0103, .0076, .0042};
1159 NV_FLOAT32 coeff[2] = {.9085, .3771};
1169 NV_CHAR level_unit[DEFAULT_LEVEL_UNIT_TYPES][DEFAULT_LEVEL_UNIT_SIZE] = {
1170 "Unknown",
"feet",
"meters",
"knots",
"knots^2"};
1174 NV_CHAR dir_unit[DEFAULT_DIR_UNIT_TYPES][DEFAULT_DIR_UNIT_SIZE] = {
1175 "Unknown",
"degrees true",
"degrees"};
1179 NV_CHAR restriction[DEFAULT_RESTRICTION_TYPES][DEFAULT_RESTRICTION_SIZE] = {
1180 "Public Domain",
"DoD/DoD Contractors Only"};
1184 NV_CHAR legalese[DEFAULT_LEGALESES][DEFAULT_LEGALESE_SIZE] = {
"NULL"};
1188 NV_CHAR datum[DEFAULT_DATUM_TYPES][DEFAULT_DATUM_SIZE] = {
1192 "Mean Lower Low Water",
1194 "Mean Higher High Water",
1195 "Mean Lower High Water",
1196 "Mean Higher Low Water",
1197 "Mean Low Water Springs",
1198 "Mean Lower Low Water Springs",
1199 "Mean Low Water Neaps",
1200 "Mean High Water Neaps",
1201 "Mean High Water Springs",
1202 "Mean Higher High Water Springs",
1203 "Indian Spring Low Water",
1204 "Equatorial Spring Low Water",
1205 "Lowest Normal Low Water",
1207 "Lowest Possible Low Water",
1208 "Lowest Astronomical Tide",
1209 "International Great Lakes Datum(1955)",
1210 "Lower Low Water, Large Tide",
1211 "Lowest Normal Tide",
1212 "Higher High Water, Large Tide",
1214 "Higher High Water, Mean Tide",
1215 "Lower Low Water, Mean Tide",
1217 "World Geodetic System (1984)",
1218 "National Geodetic Vertical Datum",
1219 "Gulf Coast Low Water Datum",
1220 "Approximate Level of Mean Sea Level",
1221 "Approximate Level of Mean Low Water",
1222 "Approximate Level of Mean Lower Low Water",
1223 "Approximate Level of Mean High Water",
1224 "Approximate Level of Mean Higher High Water",
1225 "Approximate Level of Mean Lower High Water",
1226 "Approximate Level of Mean Higher Low Water",
1227 "Approximate Level of Mean Low Water Springs",
1228 "Approximate Level of Mean Lower Low Water Springs",
1229 "Approximate Level of Mean Low Water Neaps",
1230 "Approximate Level of Mean High Water Neaps",
1231 "Approximate Level of Mean High Water Springs",
1232 "Approximate Level of Mean Higher High Water Springs",
1233 "Approximate Level of Indian Spring Low Water",
1234 "Approximate Level of Equatorial Spring Low Water",
1235 "Approximate Level of Lowest Normal Low Water",
1236 "Approximate Level of Lowest Low Water",
1237 "Approximate Level of Lowest Possible Low Water",
1238 "Approximate Level of Lowest Astronomical Tide",
1239 "Approximate Level of International Great Lakes Datum (1955)",
1240 "Approximate Level of Lower Low Water, Large Tide",
1241 "Approximate Level of Lowest Normal Tide",
1242 "Approximate Level of Higher High Water, Large Tide",
1243 "Approximate Level of Mean Water Level",
1244 "Approximate Level of Higher High Water, Mean Tide",
1245 "Approximate Level of Lower Low Water, Mean Tide",
1246 "Approximate Level of Mean Tide Level",
1247 "Approximate Level of World Geodetic System (1984)",
1248 "Approximate Level of National Geodetic Vertical Datum",
1249 "Approximate Level of Gulf Coast Low Water Datum"};
1253 NV_CHAR country[DEFAULT_COUNTRIES][DEFAULT_COUNTRY_SIZE] = {
1262 "Antigua & Barbuda",
1280 "Bosnia & Herzegovina",
1285 "British Indian Ocean Territory",
1295 "Central African Rep.",
1300 "Cocos (Keeling) Islands",
1303 "Congo (Dem. Rep.)",
1315 "Dominican Republic",
1320 "Equatorial Guinea",
1331 "French Southern & Antarctic Lands",
1348 "Heard Island & McDonald Islands",
1405 "Netherlands Antilles",
1413 "Northern Mariana Islands",
1436 "Sao Tome & Principe",
1447 "South Georgia & the South Sandwich Islands",
1453 "St Pierre & Miquelon",
1457 "Svalbard & Jan Mayen",
1469 "Trinidad & Tobago",
1473 "Turks & Caicos Is",
1477 "United Arab Emirates",
1480 "US minor outlying islands",
1486 "Virgin Islands (UK)",
1487 "Virgin Islands (US)",
1497 NV_CHAR tzfile[DEFAULT_TZFILES][DEFAULT_TZFILE_SIZE] = {
1501 ":Africa/Addis_Ababa",
1509 ":Africa/Brazzaville",
1510 ":Africa/Bujumbura",
1512 ":Africa/Casablanca",
1516 ":Africa/Dar_es_Salaam",
1523 ":Africa/Johannesburg",
1529 ":Africa/Libreville",
1532 ":Africa/Lubumbashi",
1538 ":Africa/Mogadishu",
1543 ":Africa/Nouakchott",
1544 ":Africa/Ouagadougou",
1545 ":Africa/Porto-Novo",
1552 ":America/Anchorage",
1553 ":America/Anguilla",
1555 ":America/Araguaina",
1557 ":America/Asuncion",
1559 ":America/Barbados",
1562 ":America/Boa_Vista",
1565 ":America/Buenos_Aires",
1566 ":America/Cambridge_Bay",
1569 ":America/Catamarca",
1573 ":America/Chihuahua",
1575 ":America/Costa_Rica",
1578 ":America/Danmarkshavn",
1580 ":America/Dawson_Creek",
1583 ":America/Dominica",
1584 ":America/Edmonton",
1585 ":America/Eirunepe",
1586 ":America/El_Salvador",
1587 ":America/Ensenada",
1588 ":America/Fortaleza",
1589 ":America/Glace_Bay",
1591 ":America/Goose_Bay",
1592 ":America/Grand_Turk",
1594 ":America/Guadeloupe",
1595 ":America/Guatemala",
1596 ":America/Guayaquil",
1600 ":America/Hermosillo",
1601 ":America/Indiana/Knox",
1602 ":America/Indiana/Marengo",
1603 ":America/Indianapolis",
1604 ":America/Indiana/Vevay",
1610 ":America/Kentucky/Monticello",
1613 ":America/Los_Angeles",
1614 ":America/Louisville",
1618 ":America/Martinique",
1619 ":America/Mazatlan",
1621 ":America/Menominee",
1623 ":America/Mexico_City",
1624 ":America/Miquelon",
1625 ":America/Monterrey",
1626 ":America/Montevideo",
1627 ":America/Montreal",
1628 ":America/Montserrat",
1630 ":America/New_York",
1634 ":America/North_Dakota/Center",
1636 ":America/Pangnirtung",
1637 ":America/Paramaribo",
1639 ":America/Port-au-Prince",
1640 ":America/Port_of_Spain",
1641 ":America/Porto_Velho",
1642 ":America/Puerto_Rico",
1643 ":America/Rainy_River",
1644 ":America/Rankin_Inlet",
1647 ":America/Rio_Branco",
1648 ":America/Santiago",
1649 ":America/Santo_Domingo",
1650 ":America/Sao_Paulo",
1651 ":America/Scoresbysund",
1652 ":America/Shiprock",
1653 ":America/St_Johns",
1654 ":America/St_Kitts",
1655 ":America/St_Lucia",
1656 ":America/St_Thomas",
1657 ":America/St_Vincent",
1658 ":America/Swift_Current",
1659 ":America/Tegucigalpa",
1661 ":America/Thunder_Bay",
1664 ":America/Vancouver",
1665 ":America/Whitehorse",
1666 ":America/Winnipeg",
1668 ":America/Yellowknife",
1669 ":Antarctica/Casey",
1670 ":Antarctica/Davis",
1671 ":Antarctica/DumontDUrville",
1672 ":Antarctica/Mawson",
1673 ":Antarctica/McMurdo",
1674 ":Antarctica/Palmer",
1675 ":Antarctica/South_Pole",
1676 ":Antarctica/Syowa",
1677 ":Antarctica/Vostok",
1678 ":Arctic/Longyearbyen",
1715 ":Asia/Krasnoyarsk",
1716 ":Asia/Kuala_Lumpur",
1725 ":Asia/Novosibirsk",
1747 ":Asia/Ulaanbaatar",
1750 ":Asia/Vladivostok",
1752 ":Asia/Yekaterinburg",
1755 ":Atlantic/Bermuda",
1757 ":Atlantic/Cape_Verde",
1759 ":Atlantic/Jan_Mayen",
1760 ":Atlantic/Madeira",
1761 ":Atlantic/Reykjavik",
1762 ":Atlantic/South_Georgia",
1763 ":Atlantic/Stanley",
1764 ":Atlantic/St_Helena",
1765 ":Australia/Adelaide",
1766 ":Australia/Brisbane",
1767 ":Australia/Broken_Hill",
1768 ":Australia/Darwin",
1769 ":Australia/Hobart",
1770 ":Australia/Lindeman",
1771 ":Australia/Lord_Howe",
1772 ":Australia/Melbourne",
1774 ":Australia/Sydney",
1804 ":Europe/Amsterdam",
1810 ":Europe/Bratislava",
1812 ":Europe/Bucharest",
1815 ":Europe/Copenhagen",
1817 ":Europe/Gibraltar",
1820 ":Europe/Kaliningrad",
1823 ":Europe/Ljubljana",
1825 ":Europe/Luxembourg",
1837 ":Europe/San_Marino",
1839 ":Europe/Simferopol",
1842 ":Europe/Stockholm",
1852 ":Europe/Zaporozhye",
1854 ":Indian/Antananarivo",
1856 ":Indian/Christmas",
1859 ":Indian/Kerguelen",
1862 ":Indian/Mauritius",
1866 ":Pacific/Auckland",
1870 ":Pacific/Enderbury",
1873 ":Pacific/Funafuti",
1874 ":Pacific/Galapagos",
1876 ":Pacific/Guadalcanal",
1878 ":Pacific/Honolulu",
1879 ":Pacific/Johnston",
1880 ":Pacific/Kiritimati",
1882 ":Pacific/Kwajalein",
1884 ":Pacific/Marquesas",
1890 ":Pacific/Pago_Pago",
1892 ":Pacific/Pitcairn",
1894 ":Pacific/Port_Moresby",
1895 ":Pacific/Rarotonga",
1899 ":Pacific/Tongatapu",
1914 #define require(expr) \
1917 require_expr = (int)(expr); \
1918 assert(require_expr); \
1931 #ifdef HAVE_UNISTD_H
2238 NV_U_INT32 calculate_bits(NV_U_INT32 value);
2239 void bit_pack(NV_U_BYTE *, NV_U_INT32, NV_U_INT32, NV_INT32);
2240 NV_U_INT32 bit_unpack(NV_U_BYTE *, NV_U_INT32, NV_U_INT32);
2241 NV_INT32 signed_bit_unpack(NV_U_BYTE buffer[], NV_U_INT32 start,
2242 NV_U_INT32 numbits);
2248 NV_U_INT32 record_size;
2250 NV_INT32 reference_station;
2253 NV_U_BYTE record_type;
2257 static FILE *fp = NULL;
2259 static NV_BOOL modified = NVFalse;
2260 static NV_INT32 current_record, current_index;
2261 static NV_CHAR filename[MONOLOGUE_LENGTH];
2271 static void chk_fread(
void *ptr,
size_t size,
size_t nmemb, FILE *stream) {
2273 ret = fread(ptr, size, nmemb, stream);
2281 static void chk_fwrite(
const void *ptr,
size_t size,
size_t nmemb,
2284 ret = fwrite(ptr, size, nmemb, stream);
2316 LOG_ERROR(
"\n\nRecord number = %d\n", rec->header.record_number);
2317 LOG_ERROR(
"Record size = %u\n", rec->header.record_size);
2318 LOG_ERROR(
"Record type = %u\n", rec->header.record_type);
2319 LOG_ERROR(
"Latitude = %f\n", rec->header.latitude);
2320 LOG_ERROR(
"Longitude = %f\n", rec->header.longitude);
2321 LOG_ERROR(
"Reference station = %d\n", rec->header.reference_station);
2322 LOG_ERROR(
"Tzfile = %s\n", get_tzfile(rec->header.tzfile));
2323 LOG_ERROR(
"Name = %s\n", rec->header.name);
2325 LOG_ERROR(
"Country = %s\n", get_country(rec->country));
2326 LOG_ERROR(
"Source = %s\n", rec->source);
2327 LOG_ERROR(
"Restriction = %s\n", get_restriction(rec->restriction));
2328 LOG_ERROR(
"Comments = %s\n", rec->comments);
2329 LOG_ERROR(
"Notes = %s\n", rec->notes);
2330 LOG_ERROR(
"Legalese = %s\n", get_legalese(rec->legalese));
2331 LOG_ERROR(
"Station ID context = %s\n", rec->station_id_context);
2332 LOG_ERROR(
"Station ID = %s\n", rec->station_id);
2333 LOG_ERROR(
"Date imported = %d\n", rec->date_imported);
2334 LOG_ERROR(
"Xfields = %s\n", rec->xfields);
2336 LOG_ERROR(
"Direction units = %s\n", get_dir_units(rec->direction_units));
2337 LOG_ERROR(
"Min direction = %d\n", rec->min_direction);
2338 LOG_ERROR(
"Max direction = %d\n", rec->max_direction);
2339 LOG_ERROR(
"Level units = %s\n", get_level_units(rec->level_units));
2341 if (rec->header.record_type == REFERENCE_STATION) {
2342 LOG_ERROR(
"Datum offset = %f\n", rec->datum_offset);
2343 LOG_ERROR(
"Datum = %s\n", get_datum(rec->datum));
2344 LOG_ERROR(
"Zone offset = %d\n", rec->zone_offset);
2345 LOG_ERROR(
"Expiration date = %d\n", rec->expiration_date);
2346 LOG_ERROR(
"Months on station = %d\n", rec->months_on_station);
2347 LOG_ERROR(
"Last date on station = %d\n", rec->last_date_on_station);
2348 LOG_ERROR(
"Confidence = %d\n", rec->confidence);
2349 for (i = 0; i < hd.pub.constituents; ++i) {
2350 if (rec->amplitude[i] != 0.0 || rec->epoch[i] != 0.0) {
2351 LOG_ERROR(
"Amplitude[%d] = %f\n", i, rec->amplitude[i]);
2352 LOG_ERROR(
"Epoch[%d] = %f\n", i, rec->epoch[i]);
2357 else if (rec->header.record_type == SUBORDINATE_STATION) {
2358 LOG_ERROR(
"Min time add = %d\n", rec->min_time_add);
2359 LOG_ERROR(
"Min level add = %f\n", rec->min_level_add);
2360 LOG_ERROR(
"Min level multiply = %f\n", rec->min_level_multiply);
2361 LOG_ERROR(
"Max time add = %d\n", rec->max_time_add);
2362 LOG_ERROR(
"Max level add = %f\n", rec->max_level_add);
2363 LOG_ERROR(
"Max level multiply = %f\n", rec->max_level_multiply);
2364 LOG_ERROR(
"Flood begins = %d\n", rec->flood_begins);
2365 LOG_ERROR(
"Ebb begins = %d\n", rec->ebb_begins);
2378 static void write_protect() {
2379 if (hd.pub.major_rev < LIBTCD_MAJOR_REV) {
2381 "libtcd error: can't modify TCD files created by earlier version. "
2382 "Use\nrewrite_tide_db to upgrade the TCD file.\n");
2406 const NV_CHAR *get_country(NV_INT32 num) {
2409 "libtcd error: attempt to access database when database not open\n");
2412 if (num >= 0 && num < (NV_INT32)hd.pub.countries)
return (hd.country[num]);
2433 const NV_CHAR *get_tzfile(NV_INT32 num) {
2436 "libtcd error: attempt to access database when database not open\n");
2439 if (num >= 0 && num < (NV_INT32)hd.pub.tzfiles)
return (hd.tzfile[num]);
2460 const NV_CHAR *get_station(NV_INT32 num) {
2463 "libtcd error: attempt to access database when database not open\n");
2466 if (num >= 0 && num < (NV_INT32)hd.pub.number_of_records)
2467 return (tindex[num].name);
2489 const NV_CHAR *get_constituent(NV_INT32 num) {
2492 "libtcd error: attempt to access database when database not open\n");
2495 if (num >= 0 && num < (NV_INT32)hd.pub.constituents)
2496 return (hd.constituent[num]);
2518 const NV_CHAR *get_level_units(NV_INT32 num) {
2521 "libtcd error: attempt to access database when database not open\n");
2524 if (num >= 0 && num < (NV_INT32)hd.pub.level_unit_types)
2525 return (hd.level_unit[num]);
2547 const NV_CHAR *get_dir_units(NV_INT32 num) {
2550 "libtcd error: attempt to access database when database not open\n");
2553 if (num >= 0 && num < (NV_INT32)hd.pub.dir_unit_types)
2554 return (hd.dir_unit[num]);
2576 const NV_CHAR *get_restriction(NV_INT32 num) {
2579 "libtcd error: attempt to access database when database not open\n");
2582 if (num >= 0 && num < (NV_INT32)hd.pub.restriction_types)
2583 return (hd.restriction[num]);
2606 NV_CHAR *get_pedigree(NV_INT32 num) {
return "Unknown"; }
2626 const NV_CHAR *get_datum(NV_INT32 num) {
2629 "libtcd error: attempt to access database when database not open\n");
2632 if (num >= 0 && num < (NV_INT32)hd.pub.datum_types)
return (hd.datum[num]);
2639 const NV_CHAR *get_legalese(NV_INT32 num) {
2642 "libtcd error: attempt to access database when database not open\n");
2645 if (num >= 0 && num < (NV_INT32)hd.pub.legaleses)
return (hd.legalese[num]);
2667 NV_FLOAT64 get_speed(NV_INT32 num) {
2670 "libtcd error: attempt to access database when database not open\n");
2673 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents);
2674 return hd.speed[num];
2696 NV_FLOAT32 get_equilibrium(NV_INT32 num, NV_INT32 year) {
2699 "libtcd error: attempt to access database when database not open\n");
2702 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 &&
2703 year < (NV_INT32)hd.pub.number_of_years);
2704 return hd.equilibrium[num][year];
2710 NV_FLOAT32 *get_equilibriums(NV_INT32 num) {
2713 "libtcd error: attempt to access database when database not open\n");
2716 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents);
2717 return hd.equilibrium[num];
2739 NV_FLOAT32 get_node_factor(NV_INT32 num, NV_INT32 year) {
2742 "libtcd error: attempt to access database when database not open\n");
2745 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 &&
2746 year < (NV_INT32)hd.pub.number_of_years);
2747 return hd.node_factor[num][year];
2753 NV_FLOAT32 *get_node_factors(NV_INT32 num) {
2756 "libtcd error: attempt to access database when database not open\n");
2759 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents);
2760 return hd.node_factor[num];
2789 "libtcd error: attempt to access database when database not open\n");
2793 if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
return (NVFalse);
2797 rec->record_number = num;
2798 rec->record_size = tindex[num].record_size;
2799 rec->record_type = tindex[num].record_type;
2800 rec->latitude = (NV_FLOAT64)tindex[num].lat / hd.latitude_scale;
2801 rec->longitude = (NV_FLOAT64)tindex[num].lon / hd.longitude_scale;
2802 rec->reference_station = tindex[num].reference_station;
2803 rec->tzfile = tindex[num].tzfile;
2804 strcpy(rec->name, tindex[num].name);
2806 current_index = num;
2830 if (!get_partial_tide_record(current_index + 1, rec))
return (-1);
2832 return (current_index);
2855 NV_INT32 get_nearest_partial_tide_record(NV_FLOAT64 lat, NV_FLOAT64 lon,
2857 NV_FLOAT64 diff, min_diff, lt, ln;
2858 NV_U_INT32 i, shortest = 0;
2860 min_diff = 999999999.9;
2861 for (i = 0; i < hd.pub.number_of_records; ++i) {
2862 lt = (NV_FLOAT64)tindex[i].lat / hd.latitude_scale;
2863 ln = (NV_FLOAT64)tindex[i].lon / hd.longitude_scale;
2865 diff = sqrt((lat - lt) * (lat - lt) + (lon - ln) * (lon - ln));
2867 if (diff < min_diff) {
2873 if (!get_partial_tide_record(shortest, rec))
return (-1);
2895 NV_INT32 get_time(
const NV_CHAR *
string) {
2896 NV_INT32 hour, minute, hhmm;
2899 sscanf(
string,
"%d:%d", &hour, &minute);
2903 if (
string[0] ==
'-') {
2904 if (hour < 0) hour = -hour;
2906 hhmm = -(hour * 100 + minute);
2908 hhmm = hour * 100 + minute;
2932 NV_CHAR *ret_time(NV_INT32 time) {
2933 NV_INT32 hour, minute;
2934 static NV_CHAR tname[16];
2936 hour = abs(time) / 100;
2937 assert(hour <= 99999 && hour >= -99999);
2938 minute = abs(time) % 100;
2941 sprintf(tname,
"-%02d:%02d", hour, minute);
2943 sprintf(tname,
"+%02d:%02d", hour, minute);
2952 NV_CHAR *ret_time_neat(NV_INT32 time) {
2953 NV_INT32 hour, minute;
2954 static NV_CHAR tname[16];
2956 hour = abs(time) / 100;
2957 assert(hour <= 99999 && hour >= -99999);
2958 minute = abs(time) % 100;
2961 sprintf(tname,
"-%d:%02d", hour, minute);
2963 sprintf(tname,
"+%d:%02d", hour, minute);
2965 strcpy(tname,
"0:00");
2973 NV_CHAR *ret_date(NV_U_INT32 date) {
2974 static NV_CHAR tname[30];
2976 strcpy(tname,
"NULL");
2983 sprintf(tname,
"%4u-%02u-%02u", y, m, d);
3007 "libtcd error: attempt to access database when database not open\n");
3017 static void boundscheck_monologue(
const NV_CHAR *
string) {
3019 if (strlen(
string) >= MONOLOGUE_LENGTH) {
3033 static void boundscheck_oneliner(
const NV_CHAR *
string) {
3035 if (strlen(
string) >= ONELINER_LENGTH) {
3063 static NV_CHAR *clip_string(
const NV_CHAR *
string) {
3064 static NV_CHAR new_string[MONOLOGUE_LENGTH];
3065 NV_INT32 i, l, start = -1, end = -1;
3067 boundscheck_monologue(
string);
3068 new_string[0] =
'\0';
3070 l = (int)strlen(
string);
3072 for (i = 0; i < l; ++i) {
3073 if (
string[i] !=
' ') {
3078 for (i = l - 1; i >= start; --i) {
3079 if (
string[i] !=
' ' &&
string[i] != 10 &&
string[i] != 13) {
3084 if (start > -1 && end > -1 && end >= start) {
3085 strncpy(new_string,
string + start, end - start + 1);
3086 new_string[end - start + 1] =
'\0';
3113 NV_INT32 search_station(
const NV_CHAR *
string) {
3114 static NV_CHAR last_search[ONELINER_LENGTH];
3115 static NV_U_INT32 j = 0;
3117 NV_CHAR name[ONELINER_LENGTH], search[ONELINER_LENGTH];
3121 "libtcd error: attempt to access database when database not open\n");
3125 boundscheck_oneliner(
string);
3127 for (i = 0; i < strlen(
string) + 1; ++i) search[i] = tolower(
string[i]);
3129 if (strcmp(search, last_search)) j = 0;
3131 strcpy(last_search, search);
3133 while (j < hd.pub.number_of_records) {
3134 for (i = 0; i < strlen(tindex[j].name) + 1; ++i)
3135 name[i] = tolower(tindex[j].name[i]);
3138 if (strstr(name, search))
return (j - 1);
3163 NV_INT32 find_station(
const NV_CHAR *name) {
3168 "libtcd error: attempt to access database when database not open\n");
3173 for (i = 0; i < hd.pub.number_of_records; ++i) {
3174 if (!strcmp(name, tindex[i].name))
return (i);
3198 NV_INT32 find_tzfile(
const NV_CHAR *name) {
3205 "libtcd error: attempt to access database when database not open\n");
3209 temp = clip_string(name);
3212 for (i = 0; i < hd.pub.tzfiles; ++i) {
3213 if (!strcmp(temp, get_tzfile(i))) {
3240 NV_INT32 find_country(
const NV_CHAR *name) {
3247 "libtcd error: attempt to access database when database not open\n");
3251 temp = clip_string(name);
3254 for (i = 0; i < hd.pub.countries; ++i) {
3255 if (!strcmp(temp, get_country(i))) {
3282 NV_INT32 find_level_units(
const NV_CHAR *name) {
3289 "libtcd error: attempt to access database when database not open\n");
3293 temp = clip_string(name);
3296 for (i = 0; i < hd.pub.level_unit_types; ++i) {
3297 if (!strcmp(get_level_units(i), temp)) {
3324 NV_INT32 find_dir_units(
const NV_CHAR *name) {
3331 "libtcd error: attempt to access database when database not open\n");
3335 temp = clip_string(name);
3338 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
3339 if (!strcmp(get_dir_units(i), temp)) {
3367 NV_INT32 find_pedigree(
const NV_CHAR *name) {
return 0; }
3388 NV_INT32 find_datum(
const NV_CHAR *name) {
3395 "libtcd error: attempt to access database when database not open\n");
3399 temp = clip_string(name);
3402 for (i = 0; i < hd.pub.datum_types; ++i) {
3403 if (!strcmp(get_datum(i), temp)) {
3415 NV_INT32 find_legalese(
const NV_CHAR *name) {
3422 "libtcd error: attempt to access database when database not open\n");
3426 temp = clip_string(name);
3429 for (i = 0; i < hd.pub.legaleses; ++i) {
3430 if (!strcmp(get_legalese(i), temp)) {
3458 NV_INT32 find_constituent(
const NV_CHAR *name) {
3464 "libtcd error: attempt to access database when database not open\n");
3468 temp = clip_string(name);
3470 for (i = 0; i < hd.pub.constituents; ++i) {
3471 if (!strcmp(get_constituent(i), temp))
return (i);
3495 NV_INT32 find_restriction(
const NV_CHAR *name) {
3502 "libtcd error: attempt to access database when database not open\n");
3506 temp = clip_string(name);
3509 for (i = 0; i < hd.pub.restriction_types; ++i) {
3510 if (!strcmp(get_restriction(i), temp)) {
3536 void set_speed(NV_INT32 num, NV_FLOAT64 value) {
3539 "libtcd error: attempt to access database when database not open\n");
3543 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents);
3545 LOG_ERROR(
"libtcd set_speed: somebody tried to set a negative speed (%f)\n",
3549 hd.speed[num] = value;
3573 void set_equilibrium(NV_INT32 num, NV_INT32 year, NV_FLOAT32 value) {
3576 "libtcd error: attempt to access database when database not open\n");
3580 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 &&
3581 year < (NV_INT32)hd.pub.number_of_years);
3582 hd.equilibrium[num][year] = value;
3606 void set_node_factor(NV_INT32 num, NV_INT32 year, NV_FLOAT32 value) {
3609 "libtcd error: attempt to access database when database not open\n");
3613 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 &&
3614 year < (NV_INT32)hd.pub.number_of_years);
3617 "libtcd set_node_factor: somebody tried to set a negative or zero node "
3622 hd.node_factor[num][year] = value;
3673 "libtcd error: attempt to access database when database not open\n");
3679 if (strlen(name) + 1 > hd.tzfile_size) {
3680 LOG_ERROR(
"libtcd error: tzfile exceeds size limit (%u).\n",
3682 LOG_ERROR(
"The offending input is: %s\n", name);
3686 if (hd.pub.tzfiles == hd.max_tzfiles) {
3687 LOG_ERROR(
"You have exceeded the maximum number of tzfile types!\n");
3688 LOG_ERROR(
"You cannot add any new tzfile types.\n");
3689 LOG_ERROR(
"Modify the DEFAULT_TZFILE_BITS and rebuild the database.\n");
3693 c_name = clip_string(name);
3695 hd.tzfile[hd.pub.tzfiles] =
3696 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3698 if (hd.tzfile[hd.pub.tzfiles] == NULL) {
3699 perror(
"Allocating new tzfile string");
3703 strcpy(hd.tzfile[hd.pub.tzfiles++], c_name);
3704 if (db) *db = hd.pub;
3706 return (hd.pub.tzfiles - 1);
3732 "libtcd error: attempt to access database when database not open\n");
3738 if (strlen(name) + 1 > hd.country_size) {
3739 LOG_ERROR(
"libtcd error: country exceeds size limit (%u).\n",
3741 LOG_ERROR(
"The offending input is: %s\n", name);
3745 if (hd.pub.countries == hd.max_countries) {
3746 LOG_ERROR(
"You have exceeded the maximum number of country names!\n");
3747 LOG_ERROR(
"You cannot add any new country names.\n");
3748 LOG_ERROR(
"Modify the DEFAULT_COUNTRY_BITS and rebuild the database.\n");
3752 c_name = clip_string(name);
3754 hd.country[hd.pub.countries] =
3755 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3757 if (hd.country[hd.pub.countries] == NULL) {
3758 perror(
"Allocating new country string");
3762 strcpy(hd.country[hd.pub.countries++], c_name);
3763 if (db) *db = hd.pub;
3765 return (hd.pub.countries - 1);
3791 "libtcd error: attempt to access database when database not open\n");
3797 if (strlen(name) + 1 > hd.datum_size) {
3798 LOG_ERROR(
"libtcd error: datum exceeds size limit (%u).\n", hd.datum_size);
3799 LOG_ERROR(
"The offending input is: %s\n", name);
3803 if (hd.pub.datum_types == hd.max_datum_types) {
3804 LOG_ERROR(
"You have exceeded the maximum number of datum types!\n");
3805 LOG_ERROR(
"You cannot add any new datum types.\n");
3806 LOG_ERROR(
"Modify the DEFAULT_DATUM_BITS and rebuild the database.\n");
3810 c_name = clip_string(name);
3812 hd.datum[hd.pub.datum_types] =
3813 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3815 if (hd.datum[hd.pub.datum_types] == NULL) {
3816 perror(
"Allocating new datum string");
3820 strcpy(hd.datum[hd.pub.datum_types++], c_name);
3821 if (db) *db = hd.pub;
3823 return (hd.pub.datum_types - 1);
3834 "libtcd error: attempt to access database when database not open\n");
3840 if (strlen(name) + 1 > hd.legalese_size) {
3841 LOG_ERROR(
"libtcd error: legalese exceeds size limit (%u).\n",
3843 LOG_ERROR(
"The offending input is: %s\n", name);
3847 if (hd.pub.legaleses == hd.max_legaleses) {
3848 LOG_ERROR(
"You have exceeded the maximum number of legaleses!\n");
3849 LOG_ERROR(
"You cannot add any new legaleses.\n");
3850 LOG_ERROR(
"Modify the DEFAULT_LEGALESE_BITS and rebuild the database.\n");
3854 c_name = clip_string(name);
3856 hd.legalese[hd.pub.legaleses] =
3857 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3859 if (hd.legalese[hd.pub.legaleses] == NULL) {
3860 perror(
"Allocating new legalese string");
3864 strcpy(hd.legalese[hd.pub.legaleses++], c_name);
3865 if (db) *db = hd.pub;
3867 return (hd.pub.legaleses - 1);
3893 "libtcd error: attempt to access database when database not open\n");
3899 if (strlen(name) + 1 > hd.restriction_size) {
3900 LOG_ERROR(
"libtcd error: restriction exceeds size limit (%u).\n",
3901 hd.restriction_size);
3902 LOG_ERROR(
"The offending input is: %s\n", name);
3906 if (hd.pub.restriction_types == hd.max_restriction_types) {
3907 LOG_ERROR(
"You have exceeded the maximum number of restriction types!\n");
3908 LOG_ERROR(
"You cannot add any new restriction types.\n");
3910 "Modify the DEFAULT_RESTRICTION_BITS and rebuild the database.\n");
3914 c_name = clip_string(name);
3916 hd.restriction[hd.pub.restriction_types] =
3917 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3919 if (hd.restriction[hd.pub.restriction_types] == NULL) {
3920 perror(
"Allocating new restriction string");
3924 strcpy(hd.restriction[hd.pub.restriction_types++], c_name);
3925 if (db) *db = hd.pub;
3927 return (hd.pub.restriction_types - 1);
3933 NV_INT32 find_or_add_restriction(
const NV_CHAR *name,
DB_HEADER_PUBLIC *db) {
3935 ret = find_restriction(name);
3936 if (ret < 0) ret = add_restriction(name, db);
3946 ret = find_tzfile(name);
3947 if (ret < 0) ret = add_tzfile(name, db);
3957 ret = find_country(name);
3958 if (ret < 0) ret = add_country(name, db);
3968 ret = find_datum(name);
3969 if (ret < 0) ret = add_datum(name, db);
3979 ret = find_legalese(name);
3980 if (ret < 0) ret = add_legalese(name, db);
4011 if (rec.max_time_add == rec.min_time_add &&
4012 rec.max_level_add == rec.min_level_add &&
4013 rec.max_level_multiply == rec.min_level_multiply &&
4014 rec.max_avg_level == 0 && rec.min_avg_level == 0 &&
4015 rec.max_direction == 361 && rec.min_direction == 361 &&
4016 rec.flood_begins == NULLSLACKOFFSET && rec.ebb_begins == NULLSLACKOFFSET)
4039 static NV_U_INT32 header_checksum() {
4040 NV_U_INT32 checksum, i, save_pos;
4042 NV_U_INT32 crc_table[256] = {
4043 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
4044 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
4045 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
4046 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
4047 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
4048 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
4049 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
4050 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
4051 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
4052 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
4053 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
4054 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
4055 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
4056 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
4057 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
4058 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
4059 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
4060 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
4061 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
4062 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
4063 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
4064 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
4065 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
4066 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
4067 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
4068 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
4069 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
4070 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
4071 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
4072 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
4073 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
4074 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
4075 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
4076 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
4077 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
4078 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
4079 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
4080 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
4081 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
4082 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
4083 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
4084 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
4085 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D};
4089 "libtcd error: attempt to access database when database not open\n");
4093 save_pos = ftell(fp);
4095 fseek(fp, 0, SEEK_SET);
4097 if ((buf = (NV_U_BYTE *)calloc(hd.header_size,
sizeof(NV_U_BYTE))) == NULL) {
4098 perror(
"Allocating checksum buffer");
4104 assert(hd.header_size > 0);
4105 chk_fread(buf, hd.header_size, 1, fp);
4106 for (i = 0; i < (NV_U_INT32)hd.header_size; ++i) {
4107 checksum = crc_table[(checksum ^ buf[i]) & 0xff] ^ (checksum >> 8);
4113 fseek(fp, save_pos, SEEK_SET);
4134 static NV_U_INT32 old_header_checksum() {
4135 NV_U_INT32 checksum, i, save_pos;
4140 "libtcd error: attempt to access database when database not open\n");
4144 save_pos = ftell(fp);
4148 fseek(fp, 0, SEEK_SET);
4150 if ((buf = (NV_U_BYTE *)calloc(hd.header_size,
sizeof(NV_U_BYTE))) == NULL) {
4151 perror(
"Allocating checksum buffer");
4155 chk_fread(buf, hd.header_size, 1, fp);
4157 for (i = 0; i < hd.header_size; ++i) checksum += buf[i];
4161 fseek(fp, save_pos, SEEK_SET);
4171 static NV_CHAR *curtime() {
4172 static NV_CHAR buf[ONELINER_LENGTH];
4173 time_t t = time(NULL);
4174 require(strftime(buf, ONELINER_LENGTH,
"%Y-%m-%d %H:%M %Z", localtime(&t)) >
4183 static NV_U_INT32 bits2bytes(NV_U_INT32 nbits) {
4184 if (nbits % 8)
return nbits / 8 + 1;
4204 static void write_tide_db_header() {
4205 NV_U_INT32 i, size, pos;
4206 NV_INT32 start, temp_int;
4207 static NV_CHAR zero = 0;
4208 NV_U_BYTE *buf, checksum_c[4];
4212 "libtcd error: attempt to access database when database not open\n");
4217 fseek(fp, 0, SEEK_SET);
4219 fprintf(fp,
"[VERSION] = %s\n", LIBTCD_VERSION);
4220 fprintf(fp,
"[MAJOR REV] = %u\n", LIBTCD_MAJOR_REV);
4221 fprintf(fp,
"[MINOR REV] = %u\n", LIBTCD_MINOR_REV);
4223 fprintf(fp,
"[LAST MODIFIED] = %s\n", curtime());
4225 fprintf(fp,
"[HEADER SIZE] = %u\n", hd.header_size);
4226 fprintf(fp,
"[NUMBER OF RECORDS] = %u\n", hd.pub.number_of_records);
4228 fprintf(fp,
"[START YEAR] = %d\n", hd.pub.start_year);
4229 fprintf(fp,
"[NUMBER OF YEARS] = %u\n", hd.pub.number_of_years);
4231 fprintf(fp,
"[SPEED BITS] = %u\n", hd.speed_bits);
4232 fprintf(fp,
"[SPEED SCALE] = %u\n", hd.speed_scale);
4233 fprintf(fp,
"[SPEED OFFSET] = %d\n", hd.speed_offset);
4234 fprintf(fp,
"[EQUILIBRIUM BITS] = %u\n", hd.equilibrium_bits);
4235 fprintf(fp,
"[EQUILIBRIUM SCALE] = %u\n", hd.equilibrium_scale);
4236 fprintf(fp,
"[EQUILIBRIUM OFFSET] = %d\n", hd.equilibrium_offset);
4237 fprintf(fp,
"[NODE BITS] = %u\n", hd.node_bits);
4238 fprintf(fp,
"[NODE SCALE] = %u\n", hd.node_scale);
4239 fprintf(fp,
"[NODE OFFSET] = %d\n", hd.node_offset);
4240 fprintf(fp,
"[AMPLITUDE BITS] = %u\n", hd.amplitude_bits);
4241 fprintf(fp,
"[AMPLITUDE SCALE] = %u\n", hd.amplitude_scale);
4242 fprintf(fp,
"[EPOCH BITS] = %u\n", hd.epoch_bits);
4243 fprintf(fp,
"[EPOCH SCALE] = %u\n", hd.epoch_scale);
4245 fprintf(fp,
"[RECORD TYPE BITS] = %u\n", hd.record_type_bits);
4246 fprintf(fp,
"[LATITUDE BITS] = %u\n", hd.latitude_bits);
4247 fprintf(fp,
"[LATITUDE SCALE] = %u\n", hd.latitude_scale);
4248 fprintf(fp,
"[LONGITUDE BITS] = %u\n", hd.longitude_bits);
4249 fprintf(fp,
"[LONGITUDE SCALE] = %u\n", hd.longitude_scale);
4250 fprintf(fp,
"[RECORD SIZE BITS] = %u\n", hd.record_size_bits);
4252 fprintf(fp,
"[STATION BITS] = %u\n", hd.station_bits);
4254 fprintf(fp,
"[DATUM OFFSET BITS] = %u\n", hd.datum_offset_bits);
4255 fprintf(fp,
"[DATUM OFFSET SCALE] = %u\n", hd.datum_offset_scale);
4256 fprintf(fp,
"[DATE BITS] = %u\n", hd.date_bits);
4257 fprintf(fp,
"[MONTHS ON STATION BITS] = %u\n", hd.months_on_station_bits);
4258 fprintf(fp,
"[CONFIDENCE VALUE BITS] = %u\n", hd.confidence_value_bits);
4260 fprintf(fp,
"[TIME BITS] = %u\n", hd.time_bits);
4261 fprintf(fp,
"[LEVEL ADD BITS] = %u\n", hd.level_add_bits);
4262 fprintf(fp,
"[LEVEL ADD SCALE] = %u\n", hd.level_add_scale);
4263 fprintf(fp,
"[LEVEL MULTIPLY BITS] = %u\n", hd.level_multiply_bits);
4264 fprintf(fp,
"[LEVEL MULTIPLY SCALE] = %u\n", hd.level_multiply_scale);
4265 fprintf(fp,
"[DIRECTION BITS] = %u\n", hd.direction_bits);
4267 fprintf(fp,
"[LEVEL UNIT BITS] = %u\n", hd.level_unit_bits);
4268 fprintf(fp,
"[LEVEL UNIT TYPES] = %u\n", hd.pub.level_unit_types);
4269 fprintf(fp,
"[LEVEL UNIT SIZE] = %u\n", hd.level_unit_size);
4271 fprintf(fp,
"[DIRECTION UNIT BITS] = %u\n", hd.dir_unit_bits);
4272 fprintf(fp,
"[DIRECTION UNIT TYPES] = %u\n", hd.pub.dir_unit_types);
4273 fprintf(fp,
"[DIRECTION UNIT SIZE] = %u\n", hd.dir_unit_size);
4275 fprintf(fp,
"[RESTRICTION BITS] = %u\n", hd.restriction_bits);
4276 fprintf(fp,
"[RESTRICTION TYPES] = %u\n", hd.pub.restriction_types);
4277 fprintf(fp,
"[RESTRICTION SIZE] = %u\n", hd.restriction_size);
4279 fprintf(fp,
"[DATUM BITS] = %u\n", hd.datum_bits);
4280 fprintf(fp,
"[DATUM TYPES] = %u\n", hd.pub.datum_types);
4281 fprintf(fp,
"[DATUM SIZE] = %u\n", hd.datum_size);
4283 fprintf(fp,
"[LEGALESE BITS] = %u\n", hd.legalese_bits);
4284 fprintf(fp,
"[LEGALESE TYPES] = %u\n", hd.pub.legaleses);
4285 fprintf(fp,
"[LEGALESE SIZE] = %u\n", hd.legalese_size);
4287 fprintf(fp,
"[CONSTITUENT BITS] = %u\n", hd.constituent_bits);
4288 fprintf(fp,
"[CONSTITUENTS] = %u\n", hd.pub.constituents);
4289 fprintf(fp,
"[CONSTITUENT SIZE] = %u\n", hd.constituent_size);
4291 fprintf(fp,
"[TZFILE BITS] = %u\n", hd.tzfile_bits);
4292 fprintf(fp,
"[TZFILES] = %u\n", hd.pub.tzfiles);
4293 fprintf(fp,
"[TZFILE SIZE] = %u\n", hd.tzfile_size);
4295 fprintf(fp,
"[COUNTRY BITS] = %u\n", hd.country_bits);
4296 fprintf(fp,
"[COUNTRIES] = %u\n", hd.pub.countries);
4297 fprintf(fp,
"[COUNTRY SIZE] = %u\n", hd.country_size);
4299 fprintf(fp,
"[END OF FILE] = %u\n", hd.end_of_file);
4300 fprintf(fp,
"[END OF ASCII HEADER DATA]\n");
4306 for (i = start; i < hd.header_size; ++i) chk_fwrite(&zero, 1, 1, fp);
4311 bit_pack(checksum_c, 0, 32, header_checksum());
4312 chk_fwrite(checksum_c, 4, 1, fp);
4319 size = hd.pub.level_unit_types * hd.level_unit_size;
4321 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4322 perror(
"Allocating unit write buffer");
4325 memset(buf, 0, size);
4327 for (i = 0; i < hd.pub.level_unit_types; ++i) {
4328 assert(strlen(hd.level_unit[i]) + 1 <= hd.level_unit_size);
4329 strcpy((NV_CHAR *)&buf[pos], hd.level_unit[i]);
4330 pos += hd.level_unit_size;
4333 chk_fwrite(buf, pos, 1, fp);
4339 size = hd.pub.dir_unit_types * hd.dir_unit_size;
4341 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4342 perror(
"Allocating unit write buffer");
4345 memset(buf, 0, size);
4347 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
4348 assert(strlen(hd.dir_unit[i]) + 1 <= hd.dir_unit_size);
4349 strcpy((NV_CHAR *)&buf[pos], hd.dir_unit[i]);
4350 pos += hd.dir_unit_size;
4353 chk_fwrite(buf, pos, 1, fp);
4359 size = hd.max_restriction_types * hd.restriction_size;
4361 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4362 perror(
"Allocating restriction write buffer");
4365 memset(buf, 0, size);
4367 for (i = 0; i < hd.max_restriction_types; ++i) {
4368 if (i == hd.pub.restriction_types)
break;
4369 assert(strlen(hd.restriction[i]) + 1 <= hd.restriction_size);
4370 strcpy((NV_CHAR *)&buf[pos], hd.restriction[i]);
4371 pos += hd.restriction_size;
4373 memcpy(&buf[pos],
"__END__", 7);
4375 chk_fwrite(buf, size, 1, fp);
4381 size = hd.max_tzfiles * hd.tzfile_size;
4383 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4384 perror(
"Allocating tzfile write buffer");
4387 memset(buf, 0, size);
4389 for (i = 0; i < hd.max_tzfiles; ++i) {
4390 if (i == hd.pub.tzfiles)
break;
4391 assert(strlen(hd.tzfile[i]) + 1 <= hd.tzfile_size);
4392 strcpy((NV_CHAR *)&buf[pos], hd.tzfile[i]);
4393 pos += hd.tzfile_size;
4395 memcpy(&buf[pos],
"__END__", 7);
4397 chk_fwrite(buf, size, 1, fp);
4403 size = hd.max_countries * hd.country_size;
4405 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4406 perror(
"Allocating country write buffer");
4409 memset(buf, 0, size);
4411 for (i = 0; i < hd.max_countries; ++i) {
4412 if (i == hd.pub.countries)
break;
4413 assert(strlen(hd.country[i]) + 1 <= hd.country_size);
4414 strcpy((NV_CHAR *)&buf[pos], hd.country[i]);
4415 pos += hd.country_size;
4417 memcpy(&buf[pos],
"__END__", 7);
4419 chk_fwrite(buf, size, 1, fp);
4425 size = hd.max_datum_types * hd.datum_size;
4427 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4428 perror(
"Allocating datum write buffer");
4431 memset(buf, 0, size);
4433 for (i = 0; i < hd.max_datum_types; ++i) {
4434 if (i == hd.pub.datum_types)
break;
4435 assert(strlen(hd.datum[i]) + 1 <= hd.datum_size);
4436 strcpy((NV_CHAR *)&buf[pos], hd.datum[i]);
4437 pos += hd.datum_size;
4439 memcpy(&buf[pos],
"__END__", 7);
4441 chk_fwrite(buf, size, 1, fp);
4447 size = hd.max_legaleses * hd.legalese_size;
4449 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4450 perror(
"Allocating legalese write buffer");
4453 memset(buf, 0, size);
4455 for (i = 0; i < hd.max_legaleses; ++i) {
4456 if (i == hd.pub.legaleses)
break;
4457 assert(strlen(hd.legalese[i]) + 1 <= hd.legalese_size);
4458 strcpy((NV_CHAR *)&buf[pos], hd.legalese[i]);
4459 pos += hd.legalese_size;
4461 memcpy(&buf[pos],
"__END__", 7);
4463 chk_fwrite(buf, size, 1, fp);
4469 size = hd.pub.constituents * hd.constituent_size;
4471 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4472 perror(
"Allocating constituent write buffer");
4475 memset(buf, 0, size);
4477 for (i = 0; i < hd.pub.constituents; ++i) {
4478 assert(strlen(hd.constituent[i]) + 1 <= hd.constituent_size);
4479 strcpy((NV_CHAR *)&buf[pos], hd.constituent[i]);
4480 pos += hd.constituent_size;
4483 chk_fwrite(buf, pos, 1, fp);
4491 size = bits2bytes(hd.pub.constituents * hd.speed_bits);
4493 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4494 perror(
"Allocating speed write buffer");
4497 memset(buf, 0, size);
4499 for (i = 0; i < hd.pub.constituents; ++i) {
4500 temp_int = NINT(hd.speed[i] * hd.speed_scale) - hd.speed_offset;
4501 assert(temp_int >= 0);
4502 bit_pack(buf, pos, hd.speed_bits, temp_int);
4503 pos += hd.speed_bits;
4506 chk_fwrite(buf, size, 1, fp);
4512 size = bits2bytes(hd.pub.constituents * hd.pub.number_of_years *
4513 hd.equilibrium_bits);
4515 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4516 perror(
"Allocating equilibrium write buffer");
4519 memset(buf, 0, size);
4521 for (i = 0; i < hd.pub.constituents; ++i) {
4523 for (j = 0; j < hd.pub.number_of_years; ++j) {
4524 temp_int = NINT(hd.equilibrium[i][j] * hd.equilibrium_scale) -
4525 hd.equilibrium_offset;
4526 assert(temp_int >= 0);
4527 bit_pack(buf, pos, hd.equilibrium_bits, temp_int);
4528 pos += hd.equilibrium_bits;
4532 chk_fwrite(buf, size, 1, fp);
4539 bits2bytes(hd.pub.constituents * hd.pub.number_of_years * hd.node_bits);
4541 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4542 perror(
"Allocating node write buffer");
4545 memset(buf, 0, size);
4547 for (i = 0; i < hd.pub.constituents; ++i) {
4549 for (j = 0; j < hd.pub.number_of_years; ++j) {
4550 temp_int = NINT(hd.node_factor[i][j] * hd.node_scale) - hd.node_offset;
4551 assert(temp_int >= 0);
4552 bit_pack(buf, pos, hd.node_bits, temp_int);
4553 pos += hd.node_bits;
4557 chk_fwrite(buf, size, 1, fp);
4588 static void unpack_string(NV_U_BYTE *buf, NV_U_INT32 bufsize, NV_U_INT32 *pos,
4589 NV_CHAR *outbuf, NV_U_INT32 outbuflen,
4590 const NV_CHAR *desc) {
4600 for (i = 0; c; ++i) {
4601 assert(*pos < bufsize);
4602 c = bit_unpack(buf, *pos, 8);
4604 if (i < outbuflen) {
4606 }
else if (i == outbuflen) {
4609 LOG_ERROR(
"libtcd warning: truncating overlong %s\n", desc);
4610 LOG_ERROR(
"The offending string starts with:\n%s\n", outbuf);
4638 static void unpack_partial_tide_record(NV_U_BYTE *buf, NV_U_INT32 bufsize,
4648 rec->header.record_size = bit_unpack(buf, *pos, hd.record_size_bits);
4649 *pos += hd.record_size_bits;
4651 rec->header.record_type = bit_unpack(buf, *pos, hd.record_type_bits);
4652 *pos += hd.record_type_bits;
4654 temp_int = signed_bit_unpack(buf, *pos, hd.latitude_bits);
4655 rec->header.latitude = (NV_FLOAT64)temp_int / hd.latitude_scale;
4656 *pos += hd.latitude_bits;
4658 temp_int = signed_bit_unpack(buf, *pos, hd.longitude_bits);
4659 rec->header.longitude = (NV_FLOAT64)temp_int / hd.longitude_scale;
4660 *pos += hd.longitude_bits;
4665 rec->header.tzfile = bit_unpack(buf, *pos, hd.tzfile_bits);
4666 *pos += hd.tzfile_bits;
4668 unpack_string(buf, bufsize, pos, rec->header.name, ONELINER_LENGTH,
4671 rec->header.reference_station = signed_bit_unpack(buf, *pos, hd.station_bits);
4672 *pos += hd.station_bits;
4674 assert(*pos <= bufsize * 8);
4697 static NV_INT32 read_partial_tide_record(NV_INT32 num,
TIDE_RECORD *rec) {
4699 NV_U_INT32 maximum_possible_size, pos;
4703 "libtcd error: attempt to access database when database not open\n");
4712 maximum_possible_size = hd.record_size_bits + hd.record_type_bits +
4713 hd.latitude_bits + hd.longitude_bits +
4714 hd.tzfile_bits + (ONELINER_LENGTH * 8) +
4716 maximum_possible_size = bits2bytes(maximum_possible_size);
4718 if ((buf = (NV_U_BYTE *)calloc(maximum_possible_size,
sizeof(NV_U_BYTE))) ==
4720 perror(
"Allocating partial tide record buffer");
4724 current_record = num;
4725 fseek(fp, tindex[num].address, SEEK_SET);
4730 size_t size = fread(buf, 1, maximum_possible_size, fp);
4731 unpack_partial_tide_record(buf, size, rec, &pos);
4751 static NV_BOOL read_tide_db_header() {
4753 NV_CHAR varin[ONELINER_LENGTH], *info;
4754 NV_U_INT32 utemp, i, j, pos, size, key_count;
4755 NV_U_BYTE *buf, checksum_c[5];
4760 "libtcd error: attempt to access database when database not open\n");
4764 strcpy(hd.pub.version,
"NO VERSION");
4767 key_count =
sizeof(keys) /
sizeof(
KEY);
4770 memset(&hd, 0,
sizeof(hd));
4773 while (fgets(varin,
sizeof(varin), fp) != NULL) {
4774 if (strlen(varin) == ONELINER_LENGTH - 1) {
4775 if (varin[ONELINER_LENGTH - 2] !=
'\n') {
4776 LOG_ERROR(
"libtcd error: header line too long, begins with:\n");
4777 LOG_ERROR(
"%s\n", varin);
4778 LOG_ERROR(
"in file %s\n", filename);
4779 LOG_ERROR(
"Configured limit is %u\n", ONELINER_LENGTH - 1);
4785 if (strstr(varin,
"[END OF ASCII HEADER DATA]"))
break;
4788 info = strchr(varin,
'=');
4790 LOG_ERROR(
"libtcd error: invalid tide db header line:\n");
4791 LOG_ERROR(
"%s", varin);
4792 LOG_ERROR(
"in file %s\n", filename);
4799 for (i = 0; i < key_count; ++i) {
4800 if (strstr(varin, keys[i].keyphrase)) {
4801 if (!strcmp(keys[i].datatype,
"cstr"))
4802 strcpy((
char *)keys[i].address.cstr, clip_string(info));
4803 else if (!strcmp(keys[i].datatype,
"i32")) {
4804 if (sscanf(info,
"%d", keys[i].address.i32) != 1) {
4805 LOG_ERROR(
"libtcd error: invalid tide db header line:\n");
4806 LOG_ERROR(
"%s", varin);
4807 LOG_ERROR(
"in file %s\n", filename);
4811 }
else if (!strcmp(keys[i].datatype,
"ui32")) {
4812 if (sscanf(info,
"%u", keys[i].address.ui32) != 1) {
4813 LOG_ERROR(
"libtcd error: invalid tide db header line:\n");
4814 LOG_ERROR(
"%s", varin);
4815 LOG_ERROR(
"in file %s\n", filename);
4827 if (!strcmp(hd.pub.version,
"NO VERSION")) {
4828 LOG_ERROR(
"libtcd error: no version found in tide db header\n");
4829 LOG_ERROR(
"in file %s\n", filename);
4835 if (hd.pub.major_rev > LIBTCD_MAJOR_REV) {
4837 "libtcd error: major revision in TCD file (%u) exceeds major revision "
4840 LOG_ERROR(
"libtcd (%u). You must upgrade libtcd to read this file.\n",
4847 fseek(fp, hd.header_size, SEEK_SET);
4851 chk_fread(checksum_c, 4, 1, fp);
4852 utemp = bit_unpack(checksum_c, 0, 32);
4854 if (utemp != header_checksum()) {
4856 if (utemp != old_header_checksum()) {
4857 LOG_ERROR(
"libtcd error: header checksum error in file %s\n", filename);
4859 "Someone may have modified the ASCII portion of the header (don't do that),\n\
4860 or it may just be corrupt.\n");
4865 LOG_ERROR(
"libtcd error: header checksum error in file %s\n", filename);
4867 "Someone may have modified the ASCII portion of the header (don't do that),\n\
4868 or it may be an ancient pre-version-1.02 TCD file, or it may just be corrupt.\n\
4869 Pre-version-1.02 TCD files can be read by building libtcd with COMPAT114\n\
4875 fseek(fp, hd.header_size + 4, SEEK_SET);
4880 hd.max_restriction_types = NINT(pow(2.0, (NV_FLOAT64)hd.restriction_bits));
4884 hd.max_tzfiles = NINT(pow(2.0, (NV_FLOAT64)hd.tzfile_bits));
4888 hd.max_countries = NINT(pow(2.0, (NV_FLOAT64)hd.country_bits));
4893 hd.max_datum_types = NINT(pow(2.0, (NV_FLOAT64)hd.datum_bits));
4898 if (hd.pub.major_rev < 2)
4899 hd.max_legaleses = 1;
4901 hd.max_legaleses = NINT(pow(2.0, (NV_FLOAT64)hd.legalese_bits));
4908 (NV_CHAR **)calloc(hd.pub.level_unit_types,
sizeof(NV_CHAR *));
4910 if ((buf = (NV_U_BYTE *)calloc(hd.level_unit_size,
sizeof(NV_U_BYTE))) ==
4912 perror(
"Allocating level unit read buffer");
4916 for (i = 0; i < hd.pub.level_unit_types; ++i) {
4917 chk_fread(buf, hd.level_unit_size, 1, fp);
4919 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
4920 strcpy(hd.level_unit[i], (NV_CHAR *)buf);
4926 hd.dir_unit = (NV_CHAR **)calloc(hd.pub.dir_unit_types,
sizeof(NV_CHAR *));
4928 if ((buf = (NV_U_BYTE *)calloc(hd.dir_unit_size,
sizeof(NV_U_BYTE))) ==
4930 perror(
"Allocating dir unit read buffer");
4934 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
4935 chk_fread(buf, hd.dir_unit_size, 1, fp);
4937 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
4938 strcpy(hd.dir_unit[i], (NV_CHAR *)buf);
4946 (NV_CHAR **)calloc(hd.max_restriction_types,
sizeof(NV_CHAR *));
4948 if ((buf = (NV_U_BYTE *)calloc(hd.restriction_size,
sizeof(NV_U_BYTE))) ==
4950 perror(
"Allocating restriction read buffer");
4954 hd.pub.restriction_types = 0;
4955 for (i = 0; i < hd.max_restriction_types; ++i) {
4956 chk_fread(buf, hd.restriction_size, 1, fp);
4957 if (!strcmp((
char *)buf,
"__END__")) {
4958 hd.pub.restriction_types = i;
4962 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
4963 strcpy(hd.restriction[i], (NV_CHAR *)buf);
4966 fseek(fp, utemp + hd.max_restriction_types * hd.restriction_size, SEEK_SET);
4969 if (hd.pub.major_rev < 2)
4970 fseek(fp, hd.pedigree_size * NINT(pow(2.0, (NV_FLOAT64)hd.pedigree_bits)),
4972 hd.pub.pedigree_types = 1;
4977 hd.tzfile = (NV_CHAR **)calloc(hd.max_tzfiles,
sizeof(NV_CHAR *));
4979 if ((buf = (NV_U_BYTE *)calloc(hd.tzfile_size,
sizeof(NV_U_BYTE))) == NULL) {
4980 perror(
"Allocating tzfile read buffer");
4985 for (i = 0; i < hd.max_tzfiles; ++i) {
4986 chk_fread(buf, hd.tzfile_size, 1, fp);
4987 if (!strcmp((
char *)buf,
"__END__")) {
4991 hd.tzfile[i] = (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
4992 strcpy(hd.tzfile[i], (NV_CHAR *)buf);
4995 fseek(fp, utemp + hd.max_tzfiles * hd.tzfile_size, SEEK_SET);
5000 hd.country = (NV_CHAR **)calloc(hd.max_countries,
sizeof(NV_CHAR *));
5002 if ((buf = (NV_U_BYTE *)calloc(hd.country_size,
sizeof(NV_U_BYTE))) == NULL) {
5003 perror(
"Allocating country read buffer");
5007 hd.pub.countries = 0;
5008 for (i = 0; i < hd.max_countries; ++i) {
5009 chk_fread(buf, hd.country_size, 1, fp);
5010 if (!strcmp((
char *)buf,
"__END__")) {
5011 hd.pub.countries = i;
5014 hd.country[i] = (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5015 strcpy(hd.country[i], (NV_CHAR *)buf);
5018 fseek(fp, utemp + hd.max_countries * hd.country_size, SEEK_SET);
5023 hd.datum = (NV_CHAR **)calloc(hd.max_datum_types,
sizeof(NV_CHAR *));
5025 if ((buf = (NV_U_BYTE *)calloc(hd.datum_size,
sizeof(NV_U_BYTE))) == NULL) {
5026 perror(
"Allocating datum read buffer");
5030 hd.pub.datum_types = 0;
5031 for (i = 0; i < hd.max_datum_types; ++i) {
5032 chk_fread(buf, hd.datum_size, 1, fp);
5033 if (!strcmp((
char *)buf,
"__END__")) {
5034 hd.pub.datum_types = i;
5037 hd.datum[i] = (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5038 strcpy(hd.datum[i], (NV_CHAR *)buf);
5041 fseek(fp, utemp + hd.max_datum_types * hd.datum_size, SEEK_SET);
5045 if (hd.pub.major_rev < 2) {
5046 hd.legalese = (NV_CHAR **)malloc(
sizeof(NV_CHAR *));
5047 assert(hd.legalese != NULL);
5048 hd.legalese[0] = (NV_CHAR *)malloc(5 *
sizeof(NV_CHAR));
5049 assert(hd.legalese[0] != NULL);
5050 strcpy(hd.legalese[0],
"NULL");
5051 hd.pub.legaleses = 1;
5054 hd.legalese = (NV_CHAR **)calloc(hd.max_legaleses,
sizeof(NV_CHAR *));
5056 if ((buf = (NV_U_BYTE *)calloc(hd.legalese_size,
sizeof(NV_U_BYTE))) ==
5058 perror(
"Allocating legalese read buffer");
5062 hd.pub.legaleses = 0;
5063 for (i = 0; i < hd.max_legaleses; ++i) {
5064 chk_fread(buf, hd.legalese_size, 1, fp);
5065 if (!strcmp((
char *)buf,
"__END__")) {
5066 hd.pub.legaleses = i;
5070 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5071 strcpy(hd.legalese[i], (NV_CHAR *)buf);
5074 fseek(fp, utemp + hd.max_legaleses * hd.legalese_size, SEEK_SET);
5079 hd.constituent = (NV_CHAR **)calloc(hd.pub.constituents,
sizeof(NV_CHAR *));
5081 if ((buf = (NV_U_BYTE *)calloc(hd.constituent_size,
sizeof(NV_U_BYTE))) ==
5083 perror(
"Allocating constituent read buffer");
5087 for (i = 0; i < hd.pub.constituents; ++i) {
5088 chk_fread(buf, hd.constituent_size, 1, fp);
5090 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5091 strcpy(hd.constituent[i], (NV_CHAR *)buf);
5095 if (hd.speed_offset < 0 || hd.equilibrium_offset < 0 || hd.node_offset < 0) {
5096 LOG_ERROR(
"libtcd WARNING: File: %s\n", filename);
5098 "WARNING: This TCD file was created by a pre-version-1.11 libtcd.\n\
5099 Versions of libtcd prior to 1.11 contained a serious bug that can result\n\
5100 in overflows in the speeds, equilibrium arguments, or node factors. This\n\
5101 database should be rebuilt from the original data if possible.\n");
5108 hd.speed = (NV_FLOAT64 *)calloc(hd.pub.constituents,
sizeof(NV_FLOAT64));
5112 if (hd.pub.major_rev < 2)
5113 size = ((hd.pub.constituents * hd.speed_bits) / 8) + 1;
5115 size = bits2bytes(hd.pub.constituents * hd.speed_bits);
5117 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
5118 perror(
"Allocating speed read buffer");
5122 chk_fread(buf, size, 1, fp);
5124 for (i = 0; i < hd.pub.constituents; ++i) {
5125 temp_int = bit_unpack(buf, pos, hd.speed_bits);
5126 hd.speed[i] = (NV_FLOAT64)(temp_int + hd.speed_offset) / hd.speed_scale;
5127 pos += hd.speed_bits;
5128 assert(hd.speed[i] >= 0.0);
5135 (NV_FLOAT32 **)calloc(hd.pub.constituents,
sizeof(NV_FLOAT32 *));
5137 for (i = 0; i < hd.pub.constituents; ++i) {
5139 (NV_FLOAT32 *)calloc(hd.pub.number_of_years,
sizeof(NV_FLOAT32));
5144 if (hd.pub.major_rev < 2)
5146 ((hd.pub.constituents * hd.pub.number_of_years * hd.equilibrium_bits) /
5150 size = bits2bytes(hd.pub.constituents * hd.pub.number_of_years *
5151 hd.equilibrium_bits);
5153 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
5154 perror(
"Allocating equilibrium read buffer");
5158 chk_fread(buf, size, 1, fp);
5160 for (i = 0; i < hd.pub.constituents; ++i) {
5161 for (j = 0; j < hd.pub.number_of_years; ++j) {
5162 temp_int = bit_unpack(buf, pos, hd.equilibrium_bits);
5163 hd.equilibrium[i][j] =
5164 (NV_FLOAT32)(temp_int + hd.equilibrium_offset) / hd.equilibrium_scale;
5165 pos += hd.equilibrium_bits;
5173 (NV_FLOAT32 **)calloc(hd.pub.constituents,
sizeof(NV_FLOAT32 *));
5175 for (i = 0; i < hd.pub.constituents; ++i) {
5177 (NV_FLOAT32 *)calloc(hd.pub.number_of_years,
sizeof(NV_FLOAT32));
5182 if (hd.pub.major_rev < 2)
5184 ((hd.pub.constituents * hd.pub.number_of_years * hd.node_bits) / 8) + 1;
5187 bits2bytes(hd.pub.constituents * hd.pub.number_of_years * hd.node_bits);
5189 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
5190 perror(
"Allocating node read buffer");
5194 chk_fread(buf, size, 1, fp);
5196 for (i = 0; i < hd.pub.constituents; ++i) {
5197 for (j = 0; j < hd.pub.number_of_years; ++j) {
5198 temp_int = bit_unpack(buf, pos, hd.node_bits);
5199 hd.node_factor[i][j] =
5200 (NV_FLOAT32)(temp_int + hd.node_offset) / hd.node_scale;
5201 pos += hd.node_bits;
5202 assert(hd.node_factor[i][j] > 0.0);
5211 if (hd.pub.number_of_records) {
5212 if ((tindex = (
TIDE_INDEX *)calloc(hd.pub.number_of_records,
5214 perror(
"Allocating tide index");
5218 tindex[0].address = ftell(fp);
5222 for (i = 0; i < hd.pub.number_of_records; ++i) {
5226 if (i) tindex[i].address = tindex[i - 1].address + rec.header.record_size;
5228 read_partial_tide_record(i, &rec);
5232 tindex[i].record_size = rec.header.record_size;
5233 tindex[i].record_type = rec.header.record_type;
5234 tindex[i].reference_station = rec.header.reference_station;
5235 assert(rec.header.tzfile >= 0);
5236 tindex[i].tzfile = rec.header.tzfile;
5237 tindex[i].lat = NINT(rec.header.latitude * hd.latitude_scale);
5238 tindex[i].lon = NINT(rec.header.longitude * hd.longitude_scale);
5240 if ((tindex[i].name = (NV_CHAR *)calloc(strlen(rec.header.name) + 1,
5241 sizeof(NV_CHAR))) == NULL) {
5242 perror(
"Allocating index name memory");
5246 strcpy(tindex[i].name, rec.header.name);
5249 current_record = -1;
5272 NV_BOOL open_tide_db(
const NV_CHAR *file) {
5274 current_record = -1;
5277 if (!strcmp(file, filename) && !modified)
5282 if ((fp = fopen(file,
"rb+")) == NULL) {
5283 if ((fp = fopen(file,
"rb")) == NULL)
return (NVFalse);
5285 boundscheck_monologue(file);
5286 strcpy(filename, file);
5287 return (read_tide_db_header());
5308 void close_tide_db() {
5312 LOG_ERROR(
"libtcd warning: close_tide_db called when no database open\n");
5319 if (modified) write_tide_db_header();
5323 assert(hd.constituent);
5324 for (i = 0; i < hd.pub.constituents; ++i) {
5325 if (hd.constituent[i] != NULL) free(hd.constituent[i]);
5327 free(hd.constituent);
5328 hd.constituent = NULL;
5330 if (hd.speed != NULL) free(hd.speed);
5332 assert(hd.equilibrium);
5333 for (i = 0; i < hd.pub.constituents; ++i) {
5334 if (hd.equilibrium[i] != NULL) free(hd.equilibrium[i]);
5336 free(hd.equilibrium);
5337 hd.equilibrium = NULL;
5339 assert(hd.node_factor);
5340 for (i = 0; i < hd.pub.constituents; ++i) {
5341 if (hd.node_factor[i] != NULL) free(hd.node_factor[i]);
5343 free(hd.node_factor);
5344 hd.node_factor = NULL;
5346 assert(hd.level_unit);
5347 for (i = 0; i < hd.pub.level_unit_types; ++i) {
5348 if (hd.level_unit[i] != NULL) free(hd.level_unit[i]);
5350 free(hd.level_unit);
5351 hd.level_unit = NULL;
5353 assert(hd.dir_unit);
5354 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
5355 if (hd.dir_unit[i] != NULL) free(hd.dir_unit[i]);
5360 assert(hd.restriction);
5361 for (i = 0; i < hd.max_restriction_types; ++i) {
5362 if (hd.restriction[i] != NULL) free(hd.restriction[i]);
5364 free(hd.restriction);
5365 hd.restriction = NULL;
5367 assert(hd.legalese);
5368 for (i = 0; i < hd.max_legaleses; ++i) {
5369 if (hd.legalese[i] != NULL) free(hd.legalese[i]);
5375 for (i = 0; i < hd.max_tzfiles; ++i) {
5376 if (hd.tzfile[i] != NULL) free(hd.tzfile[i]);
5382 for (i = 0; i < hd.max_countries; ++i) {
5383 if (hd.country[i] != NULL) free(hd.country[i]);
5389 for (i = 0; i < hd.max_datum_types; ++i) {
5390 if (hd.datum[i] != NULL) free(hd.datum[i]);
5397 for (i = 0; i < hd.pub.number_of_records; ++i) {
5398 if (tindex[i].name) free(tindex[i].name);
5439 NV_BOOL create_tide_db(
const NV_CHAR *file, NV_U_INT32 constituents,
5440 NV_CHAR
const *
const constituent[],
5441 const NV_FLOAT64 *speed, NV_INT32 start_year,
5442 NV_U_INT32 num_years,
5443 NV_FLOAT32
const *
const equilibrium[],
5444 NV_FLOAT32
const *
const node_factor[]) {
5446 NV_FLOAT64 min_value, max_value;
5451 assert(constituent);
5453 assert(equilibrium);
5454 assert(node_factor);
5455 for (i = 0; i < constituents; ++i) {
5456 if (speed[i] < 0.0) {
5458 "libtcd create_tide_db: somebody tried to set a negative speed "
5463 for (j = 0; j < num_years; ++j) {
5464 if (node_factor[i][j] <= 0.0) {
5466 "libtcd create_tide_db: somebody tried to set a negative or zero "
5467 "node factor (%f)\n",
5474 if (fp) close_tide_db();
5476 if ((fp = fopen(file,
"wb+")) == NULL) {
5483 memset(&hd, 0,
sizeof(hd));
5485 hd.pub.major_rev = LIBTCD_MAJOR_REV;
5486 hd.pub.minor_rev = LIBTCD_MINOR_REV;
5488 hd.header_size = DEFAULT_HEADER_SIZE;
5489 hd.pub.number_of_records = DEFAULT_NUMBER_OF_RECORDS;
5491 hd.pub.start_year = start_year;
5492 hd.pub.number_of_years = num_years;
5494 hd.pub.constituents = constituents;
5498 hd.constituent = (NV_CHAR **)calloc(hd.pub.constituents,
sizeof(NV_CHAR *));
5499 for (i = 0; i < hd.pub.constituents; ++i) {
5501 (NV_CHAR *)calloc(strlen(constituent[i]) + 1,
sizeof(NV_CHAR));
5502 strcpy(hd.constituent[i], constituent[i]);
5508 hd.constituent_bits = calculate_bits(hd.pub.constituents);
5512 hd.speed = (NV_FLOAT64 *)calloc(hd.pub.constituents,
sizeof(NV_FLOAT64));
5514 hd.speed_scale = DEFAULT_SPEED_SCALE;
5515 min_value = 99999999.0;
5516 max_value = -99999999.0;
5517 for (i = 0; i < hd.pub.constituents; ++i) {
5518 if (speed[i] < min_value) min_value = speed[i];
5519 if (speed[i] > max_value) max_value = speed[i];
5521 hd.speed[i] = speed[i];
5527 hd.speed_offset = (NINT(min_value * hd.speed_scale));
5528 temp_int = NINT(max_value * hd.speed_scale) - hd.speed_offset;
5529 assert(temp_int >= 0);
5530 hd.speed_bits = calculate_bits((NV_U_INT32)temp_int);
5532 assert(hd.speed_bits < 32);
5537 (NV_FLOAT32 **)calloc(hd.pub.constituents,
sizeof(NV_FLOAT32 *));
5539 hd.equilibrium_scale = DEFAULT_EQUILIBRIUM_SCALE;
5540 min_value = 99999999.0;
5541 max_value = -99999999.0;
5542 for (i = 0; i < hd.pub.constituents; ++i) {
5544 (NV_FLOAT32 *)calloc(hd.pub.number_of_years,
sizeof(NV_FLOAT32));
5545 for (j = 0; j < hd.pub.number_of_years; ++j) {
5546 if (equilibrium[i][j] < min_value) min_value = equilibrium[i][j];
5547 if (equilibrium[i][j] > max_value) max_value = equilibrium[i][j];
5549 hd.equilibrium[i][j] = equilibrium[i][j];
5556 hd.equilibrium_offset = (NINT(min_value * hd.equilibrium_scale));
5557 temp_int = NINT(max_value * hd.equilibrium_scale) - hd.equilibrium_offset;
5558 assert(temp_int >= 0);
5559 hd.equilibrium_bits = calculate_bits((NV_U_INT32)temp_int);
5564 (NV_FLOAT32 **)calloc(hd.pub.constituents,
sizeof(NV_FLOAT32 *));
5566 hd.node_scale = DEFAULT_NODE_SCALE;
5567 min_value = 99999999.0;
5568 max_value = -99999999.0;
5569 for (i = 0; i < hd.pub.constituents; ++i) {
5571 (NV_FLOAT32 *)calloc(hd.pub.number_of_years,
sizeof(NV_FLOAT32));
5572 for (j = 0; j < hd.pub.number_of_years; ++j) {
5573 if (node_factor[i][j] < min_value) min_value = node_factor[i][j];
5574 if (node_factor[i][j] > max_value) max_value = node_factor[i][j];
5576 hd.node_factor[i][j] = node_factor[i][j];
5583 hd.node_offset = (NINT(min_value * hd.node_scale));
5584 temp_int = NINT(max_value * hd.node_scale) - hd.node_offset;
5585 assert(temp_int >= 0);
5586 hd.node_bits = calculate_bits((NV_U_INT32)temp_int);
5590 hd.amplitude_bits = DEFAULT_AMPLITUDE_BITS;
5591 hd.amplitude_scale = DEFAULT_AMPLITUDE_SCALE;
5592 hd.epoch_bits = DEFAULT_EPOCH_BITS;
5593 hd.epoch_scale = DEFAULT_EPOCH_SCALE;
5595 hd.record_type_bits = DEFAULT_RECORD_TYPE_BITS;
5596 hd.latitude_bits = DEFAULT_LATITUDE_BITS;
5597 hd.latitude_scale = DEFAULT_LATITUDE_SCALE;
5598 hd.longitude_bits = DEFAULT_LONGITUDE_BITS;
5599 hd.longitude_scale = DEFAULT_LONGITUDE_SCALE;
5600 hd.record_size_bits = DEFAULT_RECORD_SIZE_BITS;
5602 hd.station_bits = DEFAULT_STATION_BITS;
5604 hd.datum_offset_bits = DEFAULT_DATUM_OFFSET_BITS;
5605 hd.datum_offset_scale = DEFAULT_DATUM_OFFSET_SCALE;
5606 hd.date_bits = DEFAULT_DATE_BITS;
5607 hd.months_on_station_bits = DEFAULT_MONTHS_ON_STATION_BITS;
5608 hd.confidence_value_bits = DEFAULT_CONFIDENCE_VALUE_BITS;
5610 hd.time_bits = DEFAULT_TIME_BITS;
5611 hd.level_add_bits = DEFAULT_LEVEL_ADD_BITS;
5612 hd.level_add_scale = DEFAULT_LEVEL_ADD_SCALE;
5613 hd.level_multiply_bits = DEFAULT_LEVEL_MULTIPLY_BITS;
5614 hd.level_multiply_scale = DEFAULT_LEVEL_MULTIPLY_SCALE;
5615 hd.direction_bits = DEFAULT_DIRECTION_BITS;
5617 hd.constituent_size = DEFAULT_CONSTITUENT_SIZE;
5618 hd.level_unit_size = DEFAULT_LEVEL_UNIT_SIZE;
5619 hd.dir_unit_size = DEFAULT_DIR_UNIT_SIZE;
5620 hd.restriction_size = DEFAULT_RESTRICTION_SIZE;
5621 hd.tzfile_size = DEFAULT_TZFILE_SIZE;
5622 hd.country_size = DEFAULT_COUNTRY_SIZE;
5623 hd.datum_size = DEFAULT_DATUM_SIZE;
5624 hd.legalese_size = DEFAULT_LEGALESE_SIZE;
5628 hd.pub.level_unit_types = DEFAULT_LEVEL_UNIT_TYPES;
5629 hd.level_unit_bits = calculate_bits(hd.pub.level_unit_types - 1);
5632 (NV_CHAR **)calloc(hd.pub.level_unit_types,
sizeof(NV_CHAR *));
5633 for (i = 0; i < hd.pub.level_unit_types; ++i) {
5635 (NV_CHAR *)calloc(strlen(level_unit[i]) + 1,
sizeof(NV_CHAR));
5636 strcpy(hd.level_unit[i], level_unit[i]);
5641 hd.pub.dir_unit_types = DEFAULT_DIR_UNIT_TYPES;
5642 hd.dir_unit_bits = calculate_bits(hd.pub.dir_unit_types - 1);
5644 hd.dir_unit = (NV_CHAR **)calloc(hd.pub.dir_unit_types,
sizeof(NV_CHAR *));
5645 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
5647 (NV_CHAR *)calloc(strlen(dir_unit[i]) + 1,
sizeof(NV_CHAR));
5648 strcpy(hd.dir_unit[i], dir_unit[i]);
5653 hd.restriction_bits = DEFAULT_RESTRICTION_BITS;
5654 hd.max_restriction_types = NINT(pow(2.0, (NV_FLOAT64)hd.restriction_bits));
5655 hd.pub.restriction_types = DEFAULT_RESTRICTION_TYPES;
5658 (NV_CHAR **)calloc(hd.max_restriction_types,
sizeof(NV_CHAR *));
5659 for (i = 0; i < hd.max_restriction_types; ++i) {
5660 if (i == hd.pub.restriction_types)
break;
5663 (NV_CHAR *)calloc(strlen(restriction[i]) + 1,
sizeof(NV_CHAR));
5664 strcpy(hd.restriction[i], restriction[i]);
5669 hd.legalese_bits = DEFAULT_LEGALESE_BITS;
5670 hd.max_legaleses = NINT(pow(2.0, (NV_FLOAT64)hd.legalese_bits));
5671 hd.pub.legaleses = DEFAULT_LEGALESES;
5673 hd.legalese = (NV_CHAR **)calloc(hd.max_legaleses,
sizeof(NV_CHAR *));
5674 for (i = 0; i < hd.max_legaleses; ++i) {
5675 if (i == hd.pub.legaleses)
break;
5678 (NV_CHAR *)calloc(strlen(legalese[i]) + 1,
sizeof(NV_CHAR));
5679 strcpy(hd.legalese[i], legalese[i]);
5684 hd.tzfile_bits = DEFAULT_TZFILE_BITS;
5685 hd.max_tzfiles = NINT(pow(2.0, (NV_FLOAT64)hd.tzfile_bits));
5686 hd.pub.tzfiles = DEFAULT_TZFILES;
5688 hd.tzfile = (NV_CHAR **)calloc(hd.max_tzfiles,
sizeof(NV_CHAR *));
5689 for (i = 0; i < hd.max_tzfiles; ++i) {
5690 if (i == hd.pub.tzfiles)
break;
5692 hd.tzfile[i] = (NV_CHAR *)calloc(strlen(tzfile[i]) + 1,
sizeof(NV_CHAR));
5693 strcpy(hd.tzfile[i], tzfile[i]);
5698 hd.country_bits = DEFAULT_COUNTRY_BITS;
5699 hd.max_countries = NINT(pow(2.0, (NV_FLOAT64)hd.country_bits));
5700 hd.pub.countries = DEFAULT_COUNTRIES;
5702 hd.country = (NV_CHAR **)calloc(hd.max_countries,
sizeof(NV_CHAR *));
5703 for (i = 0; i < hd.max_countries; ++i) {
5704 if (i == hd.pub.countries)
break;
5706 hd.country[i] = (NV_CHAR *)calloc(strlen(country[i]) + 1,
sizeof(NV_CHAR));
5707 strcpy(hd.country[i], country[i]);
5712 hd.datum_bits = DEFAULT_DATUM_BITS;
5713 hd.max_datum_types = NINT(pow(2.0, (NV_FLOAT64)hd.datum_bits));
5714 hd.pub.datum_types = DEFAULT_DATUM_TYPES;
5716 hd.datum = (NV_CHAR **)calloc(hd.max_datum_types,
sizeof(NV_CHAR *));
5717 for (i = 0; i < hd.max_datum_types; ++i) {
5718 if (i == hd.pub.datum_types)
break;
5720 hd.datum[i] = (NV_CHAR *)calloc(strlen(datum[i]) + 1,
sizeof(NV_CHAR));
5721 strcpy(hd.datum[i], datum[i]);
5731 i = (open_tide_db(file));
5735 hd.end_of_file = ftell(fp);
5739 write_tide_db_header();
5748 static NV_BOOL check_date(NV_U_INT32 date) {
5754 if (m < 1 || m > 12 || d < 1 || d > 31)
return NVFalse;
5768 static NV_BOOL check_tide_record(
TIDE_RECORD *rec) {
5770 NV_BOOL ret = NVTrue;
5773 LOG_ERROR(
"libtcd error: null pointer passed to check_tide_record\n");
5779 boundscheck_oneliner(rec->header.name);
5780 boundscheck_oneliner(rec->source);
5781 boundscheck_monologue(rec->comments);
5782 boundscheck_monologue(rec->notes);
5783 boundscheck_oneliner(rec->station_id_context);
5784 boundscheck_oneliner(rec->station_id);
5785 boundscheck_monologue(rec->xfields);
5788 if (rec->header.record_type == REFERENCE_STATION && rec->units > 0)
5789 rec->level_units = rec->units;
5792 if (rec->header.latitude < -90.0 || rec->header.latitude > 90.0 ||
5793 rec->header.longitude < -180.0 || rec->header.longitude > 180.0) {
5794 LOG_ERROR(
"libtcd error: bad coordinates in tide record\n");
5798 if (rec->header.tzfile < 0 ||
5799 rec->header.tzfile >= (NV_INT32)hd.pub.tzfiles) {
5800 LOG_ERROR(
"libtcd error: bad tzfile in tide record\n");
5804 if (rec->header.name[0] ==
'\0') {
5805 LOG_ERROR(
"libtcd error: null name in tide record\n");
5809 if (rec->country < 0 || rec->country >= (NV_INT32)hd.pub.countries) {
5810 LOG_ERROR(
"libtcd error: bad country in tide record\n");
5814 if (rec->restriction >= hd.pub.restriction_types) {
5815 LOG_ERROR(
"libtcd error: bad restriction in tide record\n");
5819 if (rec->legalese >= hd.pub.legaleses) {
5820 LOG_ERROR(
"libtcd error: bad legalese in tide record\n");
5824 if (!check_date(rec->date_imported)) {
5825 LOG_ERROR(
"libtcd error: bad date_imported in tide record\n");
5829 if (rec->direction_units >= hd.pub.dir_unit_types) {
5830 LOG_ERROR(
"libtcd error: bad direction_units in tide record\n");
5834 if (rec->min_direction < 0 || rec->min_direction > 361) {
5835 LOG_ERROR(
"libtcd error: min_direction out of range in tide record\n");
5839 if (rec->max_direction < 0 || rec->max_direction > 361) {
5840 LOG_ERROR(
"libtcd error: max_direction out of range in tide record\n");
5844 if (rec->level_units >= hd.pub.level_unit_types) {
5845 LOG_ERROR(
"libtcd error: bad units in tide record\n");
5849 switch (rec->header.record_type) {
5850 case REFERENCE_STATION:
5851 if (rec->header.reference_station != -1) {
5852 LOG_ERROR(
"libtcd error: type 1 record, reference_station != -1\n");
5856 if (rec->datum_offset < -13421.7728 || rec->datum_offset > 13421.7727) {
5857 LOG_ERROR(
"libtcd error: datum_offset out of range in tide record\n");
5861 if (rec->datum < 0 || rec->datum >= (NV_INT32)hd.pub.datum_types) {
5862 LOG_ERROR(
"libtcd error: bad datum in tide record\n");
5866 if (rec->zone_offset < -4096 || rec->zone_offset > 4095 ||
5867 rec->zone_offset % 100 >= 60) {
5868 LOG_ERROR(
"libtcd error: bad zone_offset in tide record\n");
5872 if (!check_date(rec->expiration_date)) {
5873 LOG_ERROR(
"libtcd error: bad expiration_date in tide record\n");
5877 if (rec->months_on_station > 1023) {
5879 "libtcd error: months_on_station out of range in tide record\n");
5883 if (!check_date(rec->last_date_on_station)) {
5884 LOG_ERROR(
"libtcd error: bad last_date_on_station in tide record\n");
5888 if (rec->confidence > 15) {
5889 LOG_ERROR(
"libtcd error: confidence out of range in tide record\n");
5894 for (i = 0; i < hd.pub.constituents; ++i) {
5895 if (rec->amplitude[i] < 0.0 || rec->amplitude[i] > 52.4287) {
5897 "libtcd error: constituent amplitude out of range in tide "
5903 for (i = 0; i < hd.pub.constituents; ++i) {
5904 if (rec->epoch[i] < 0.0 || rec->epoch[i] > 360.0) {
5906 "libtcd error: constituent epoch out of range in tide record\n");
5914 case SUBORDINATE_STATION:
5915 if (rec->header.reference_station < 0 ||
5916 rec->header.reference_station >= (NV_INT32)hd.pub.number_of_records) {
5917 LOG_ERROR(
"libtcd error: bad reference_station in tide record\n");
5921 if (rec->min_time_add < -4096 || rec->min_time_add > 4095 ||
5922 rec->min_time_add % 100 >= 60) {
5923 LOG_ERROR(
"libtcd error: bad min_time_add in tide record\n");
5927 if (rec->min_level_add < -65.536 || rec->min_level_add > 65.535) {
5928 LOG_ERROR(
"libtcd error: min_level_add out of range in tide record\n");
5932 if (rec->min_level_multiply < 0.0 || rec->min_level_multiply > 65.535) {
5934 "libtcd error: min_level_multiply out of range in tide record\n");
5938 if (rec->max_time_add < -4096 || rec->max_time_add > 4095 ||
5939 rec->max_time_add % 100 >= 60) {
5940 LOG_ERROR(
"libtcd error: bad max_time_add in tide record\n");
5944 if (rec->max_level_add < -65.536 || rec->max_level_add > 65.535) {
5945 LOG_ERROR(
"libtcd error: max_level_add out of range in tide record\n");
5949 if (rec->max_level_multiply < 0.0 || rec->max_level_multiply > 65.535) {
5951 "libtcd error: max_level_multiply out of range in tide record\n");
5955 if (rec->flood_begins != NULLSLACKOFFSET &&
5956 (rec->flood_begins < -4096 || rec->flood_begins > 4095 ||
5957 rec->flood_begins % 100 >= 60)) {
5958 LOG_ERROR(
"libtcd error: bad flood_begins in tide record\n");
5962 if (rec->ebb_begins != NULLSLACKOFFSET &&
5963 (rec->ebb_begins < -4096 || rec->ebb_begins > 4095 ||
5964 rec->ebb_begins % 100 >= 60)) {
5965 LOG_ERROR(
"libtcd error: bad ebb_begins in tide record\n");
5972 LOG_ERROR(
"libtcd error: invalid record_type in tide record\n");
5976 if (ret == NVFalse) dump_tide_record(rec);
5987 NV_U_INT32 i, count = 0, name_size, source_size, comments_size, notes_size,
5988 station_id_context_size, station_id_size, xfields_size;
5994 name_size = strlen(clip_string(rec->header.name)) + 1;
5995 source_size = strlen(clip_string(rec->source)) + 1;
5996 comments_size = strlen(clip_string(rec->comments)) + 1;
5997 notes_size = strlen(clip_string(rec->notes)) + 1;
5998 station_id_context_size = strlen(clip_string(rec->station_id_context)) + 1;
5999 station_id_size = strlen(clip_string(rec->station_id)) + 1;
6001 xfields_size = strlen(rec->xfields) + 1;
6003 rec->header.record_size =
6004 hd.record_size_bits + hd.record_type_bits + hd.latitude_bits +
6005 hd.longitude_bits + hd.station_bits + hd.tzfile_bits + (name_size * 8) +
6007 hd.country_bits + (source_size * 8) + hd.restriction_bits +
6008 (comments_size * 8) + (notes_size * 8) + hd.legalese_bits +
6009 (station_id_context_size * 8) + (station_id_size * 8) + hd.date_bits +
6010 (xfields_size * 8) + hd.dir_unit_bits + hd.direction_bits +
6011 hd.direction_bits + hd.level_unit_bits;
6013 switch (rec->header.record_type) {
6014 case REFERENCE_STATION:
6015 rec->header.record_size += hd.datum_offset_bits + hd.datum_bits +
6016 hd.time_bits + hd.date_bits +
6017 hd.months_on_station_bits + hd.date_bits +
6018 hd.confidence_value_bits + hd.constituent_bits;
6020 for (i = 0; i < hd.pub.constituents; ++i) {
6021 assert(rec->amplitude[i] >= 0.0);
6022 if (rec->amplitude[i] >= AMPLITUDE_EPSILON) ++count;
6025 rec->header.record_size +=
6026 (count * hd.constituent_bits + count * hd.amplitude_bits +
6027 count * hd.epoch_bits);
6031 case SUBORDINATE_STATION:
6032 rec->header.record_size += hd.time_bits + hd.level_add_bits +
6033 hd.level_multiply_bits + hd.time_bits +
6034 hd.level_add_bits + hd.level_multiply_bits +
6035 hd.time_bits + hd.time_bits;
6042 rec->header.record_size = bits2bytes(rec->header.record_size);
6049 static void pack_string(NV_U_BYTE *buf, NV_U_INT32 *pos, NV_CHAR *s) {
6050 NV_U_INT32 i, temp_size;
6054 temp_size = strlen(s) + 1;
6055 for (i = 0; i < temp_size; ++i) {
6056 bit_pack(buf, *pos, 8, s[i]);
6081 static void pack_tide_record(
TIDE_RECORD *rec, NV_U_BYTE **bufptr,
6082 NV_U_INT32 *bufsize) {
6083 NV_U_INT32 i, pos, constituent_count;
6092 boundscheck_oneliner(rec->header.name);
6093 boundscheck_oneliner(rec->source);
6094 boundscheck_monologue(rec->comments);
6095 boundscheck_monologue(rec->notes);
6096 boundscheck_oneliner(rec->station_id_context);
6097 boundscheck_oneliner(rec->station_id);
6098 boundscheck_monologue(rec->xfields);
6100 constituent_count = figure_size(rec);
6103 (NV_U_BYTE *)calloc(rec->header.record_size,
sizeof(NV_U_BYTE)))) {
6104 perror(
"libtcd can't allocate memory in pack_tide_record");
6114 bit_pack(buf, pos, hd.record_size_bits, rec->header.record_size);
6115 pos += hd.record_size_bits;
6117 bit_pack(buf, pos, hd.record_type_bits, rec->header.record_type);
6118 pos += hd.record_type_bits;
6120 temp_int = NINT(rec->header.latitude * hd.latitude_scale);
6121 bit_pack(buf, pos, hd.latitude_bits, temp_int);
6122 pos += hd.latitude_bits;
6124 temp_int = NINT(rec->header.longitude * hd.longitude_scale);
6125 bit_pack(buf, pos, hd.longitude_bits, temp_int);
6126 pos += hd.longitude_bits;
6132 bit_pack(buf, pos, hd.tzfile_bits, rec->header.tzfile);
6133 pos += hd.tzfile_bits;
6135 pack_string(buf, &pos, clip_string(rec->header.name));
6137 bit_pack(buf, pos, hd.station_bits, rec->header.reference_station);
6138 pos += hd.station_bits;
6140 bit_pack(buf, pos, hd.country_bits, rec->country);
6141 pos += hd.country_bits;
6143 pack_string(buf, &pos, clip_string(rec->source));
6145 bit_pack(buf, pos, hd.restriction_bits, rec->restriction);
6146 pos += hd.restriction_bits;
6148 pack_string(buf, &pos, clip_string(rec->comments));
6149 pack_string(buf, &pos, clip_string(rec->notes));
6151 bit_pack(buf, pos, hd.legalese_bits, rec->legalese);
6152 pos += hd.legalese_bits;
6154 pack_string(buf, &pos, clip_string(rec->station_id_context));
6155 pack_string(buf, &pos, clip_string(rec->station_id));
6157 bit_pack(buf, pos, hd.date_bits, rec->date_imported);
6158 pos += hd.date_bits;
6161 pack_string(buf, &pos, rec->xfields);
6163 bit_pack(buf, pos, hd.dir_unit_bits, rec->direction_units);
6164 pos += hd.dir_unit_bits;
6166 bit_pack(buf, pos, hd.direction_bits, rec->min_direction);
6167 pos += hd.direction_bits;
6169 bit_pack(buf, pos, hd.direction_bits, rec->max_direction);
6170 pos += hd.direction_bits;
6173 bit_pack(buf, pos, hd.level_unit_bits, rec->level_units);
6174 pos += hd.level_unit_bits;
6178 if (rec->header.record_type == REFERENCE_STATION) {
6179 temp_int = NINT(rec->datum_offset * hd.datum_offset_scale);
6180 bit_pack(buf, pos, hd.datum_offset_bits, temp_int);
6181 pos += hd.datum_offset_bits;
6183 bit_pack(buf, pos, hd.datum_bits, rec->datum);
6184 pos += hd.datum_bits;
6186 bit_pack(buf, pos, hd.time_bits, rec->zone_offset);
6187 pos += hd.time_bits;
6189 bit_pack(buf, pos, hd.date_bits, rec->expiration_date);
6190 pos += hd.date_bits;
6192 bit_pack(buf, pos, hd.months_on_station_bits, rec->months_on_station);
6193 pos += hd.months_on_station_bits;
6195 bit_pack(buf, pos, hd.date_bits, rec->last_date_on_station);
6196 pos += hd.date_bits;
6198 bit_pack(buf, pos, hd.confidence_value_bits, rec->confidence);
6199 pos += hd.confidence_value_bits;
6201 bit_pack(buf, pos, hd.constituent_bits, constituent_count);
6202 pos += hd.constituent_bits;
6204 for (i = 0; i < hd.pub.constituents; ++i) {
6205 if (rec->amplitude[i] >= AMPLITUDE_EPSILON) {
6206 bit_pack(buf, pos, hd.constituent_bits, i);
6207 pos += hd.constituent_bits;
6209 temp_int = NINT(rec->amplitude[i] * hd.amplitude_scale);
6211 bit_pack(buf, pos, hd.amplitude_bits, temp_int);
6212 pos += hd.amplitude_bits;
6214 temp_int = NINT(rec->epoch[i] * hd.epoch_scale);
6215 bit_pack(buf, pos, hd.epoch_bits, temp_int);
6216 pos += hd.epoch_bits;
6222 else if (rec->header.record_type == SUBORDINATE_STATION) {
6223 bit_pack(buf, pos, hd.time_bits, rec->min_time_add);
6224 pos += hd.time_bits;
6226 temp_int = NINT(rec->min_level_add * hd.level_add_scale);
6227 bit_pack(buf, pos, hd.level_add_bits, temp_int);
6228 pos += hd.level_add_bits;
6230 temp_int = NINT(rec->min_level_multiply * hd.level_multiply_scale);
6231 bit_pack(buf, pos, hd.level_multiply_bits, temp_int);
6232 pos += hd.level_multiply_bits;
6234 bit_pack(buf, pos, hd.time_bits, rec->max_time_add);
6235 pos += hd.time_bits;
6237 temp_int = NINT(rec->max_level_add * hd.level_add_scale);
6238 bit_pack(buf, pos, hd.level_add_bits, temp_int);
6239 pos += hd.level_add_bits;
6241 temp_int = NINT(rec->max_level_multiply * hd.level_multiply_scale);
6242 bit_pack(buf, pos, hd.level_multiply_bits, temp_int);
6243 pos += hd.level_multiply_bits;
6245 bit_pack(buf, pos, hd.time_bits, rec->flood_begins);
6246 pos += hd.time_bits;
6248 bit_pack(buf, pos, hd.time_bits, rec->ebb_begins);
6249 pos += hd.time_bits;
6253 LOG_ERROR(
"libtcd error: Record type %d is undefined\n",
6254 rec->header.record_type);
6258 *bufsize = rec->header.record_size;
6259 assert(*bufsize == bits2bytes(pos));
6284 static NV_BOOL write_tide_record(NV_INT32 num,
TIDE_RECORD *rec) {
6285 NV_U_BYTE *buf = NULL;
6286 NV_U_INT32 bufsize = 0;
6290 "libtcd error: attempt to access database when database not open\n");
6295 pack_tide_record(rec, &buf, &bufsize);
6300 fseek(fp, tindex[num].address, SEEK_SET);
6304 chk_fwrite(buf, bufsize, 1, fp);
6328 NV_INT32 read_next_tide_record(
TIDE_RECORD *rec) {
6329 return (read_tide_record(current_record + 1, rec));
6353 static void unpack_tide_record(NV_U_BYTE *buf, NV_U_INT32 bufsize,
6356 NV_U_INT32 i, j, pos, count;
6363 int r = find_dir_units(
"degrees true");
6365 rec->direction_units = (NV_U_BYTE)r;
6367 rec->min_direction = rec->max_direction = 361;
6368 rec->flood_begins = rec->ebb_begins = NULLSLACKOFFSET;
6369 rec->header.record_number = current_record;
6371 unpack_partial_tide_record(buf, bufsize, rec, &pos);
6373 switch (rec->header.record_type) {
6374 case REFERENCE_STATION:
6375 case SUBORDINATE_STATION:
6378 LOG_ERROR(
"libtcd fatal error: tried to read type %d tide record.\n",
6379 rec->header.record_type);
6381 "This version of libtcd only supports types 1 and 2. Perhaps you "
6382 "should\nupgrade.\n");
6386 switch (hd.pub.major_rev) {
6393 rec->country = bit_unpack(buf, pos, hd.country_bits);
6394 pos += hd.country_bits;
6397 pos += hd.pedigree_bits;
6399 unpack_string(buf, bufsize, &pos, rec->source, ONELINER_LENGTH,
6402 rec->restriction = bit_unpack(buf, pos, hd.restriction_bits);
6403 pos += hd.restriction_bits;
6405 unpack_string(buf, bufsize, &pos, rec->comments, MONOLOGUE_LENGTH,
6408 if (rec->header.record_type == REFERENCE_STATION) {
6409 rec->level_units = bit_unpack(buf, pos, hd.level_unit_bits);
6411 rec->units = rec->level_units;
6413 pos += hd.level_unit_bits;
6415 temp_int = signed_bit_unpack(buf, pos, hd.datum_offset_bits);
6416 rec->datum_offset = (NV_FLOAT32)temp_int / hd.datum_offset_scale;
6417 pos += hd.datum_offset_bits;
6419 rec->datum = bit_unpack(buf, pos, hd.datum_bits);
6420 pos += hd.datum_bits;
6422 rec->zone_offset = signed_bit_unpack(buf, pos, hd.time_bits);
6423 pos += hd.time_bits;
6425 rec->expiration_date = bit_unpack(buf, pos, hd.date_bits);
6426 pos += hd.date_bits;
6428 rec->months_on_station =
6429 bit_unpack(buf, pos, hd.months_on_station_bits);
6430 pos += hd.months_on_station_bits;
6432 rec->last_date_on_station = bit_unpack(buf, pos, hd.date_bits);
6433 pos += hd.date_bits;
6435 rec->confidence = bit_unpack(buf, pos, hd.confidence_value_bits);
6436 pos += hd.confidence_value_bits;
6438 for (i = 0; i < hd.pub.constituents; ++i) {
6439 rec->amplitude[i] = 0.0;
6440 rec->epoch[i] = 0.0;
6443 count = bit_unpack(buf, pos, hd.constituent_bits);
6444 pos += hd.constituent_bits;
6446 for (i = 0; i < count; ++i) {
6447 j = bit_unpack(buf, pos, hd.constituent_bits);
6448 pos += hd.constituent_bits;
6451 (NV_FLOAT32)bit_unpack(buf, pos, hd.amplitude_bits) /
6453 pos += hd.amplitude_bits;
6456 (NV_FLOAT32)bit_unpack(buf, pos, hd.epoch_bits) / hd.epoch_scale;
6457 pos += hd.epoch_bits;
6459 }
else if (rec->header.record_type == SUBORDINATE_STATION) {
6460 rec->level_units = bit_unpack(buf, pos, hd.level_unit_bits);
6461 pos += hd.level_unit_bits;
6463 rec->direction_units = bit_unpack(buf, pos, hd.dir_unit_bits);
6464 pos += hd.dir_unit_bits;
6467 pos += hd.level_unit_bits;
6469 rec->min_time_add = signed_bit_unpack(buf, pos, hd.time_bits);
6470 pos += hd.time_bits;
6472 temp_int = signed_bit_unpack(buf, pos, hd.level_add_bits);
6473 rec->min_level_add = (NV_FLOAT32)temp_int / hd.level_add_scale;
6474 pos += hd.level_add_bits;
6477 temp_int = signed_bit_unpack(buf, pos, hd.level_multiply_bits);
6478 rec->min_level_multiply =
6479 (NV_FLOAT32)temp_int / hd.level_multiply_scale;
6480 pos += hd.level_multiply_bits;
6483 pos += hd.level_add_bits;
6485 rec->min_direction = bit_unpack(buf, pos, hd.direction_bits);
6486 pos += hd.direction_bits;
6488 rec->max_time_add = signed_bit_unpack(buf, pos, hd.time_bits);
6489 pos += hd.time_bits;
6491 temp_int = signed_bit_unpack(buf, pos, hd.level_add_bits);
6492 rec->max_level_add = (NV_FLOAT32)temp_int / hd.level_add_scale;
6493 pos += hd.level_add_bits;
6496 temp_int = signed_bit_unpack(buf, pos, hd.level_multiply_bits);
6497 rec->max_level_multiply =
6498 (NV_FLOAT32)temp_int / hd.level_multiply_scale;
6499 pos += hd.level_multiply_bits;
6502 pos += hd.level_add_bits;
6504 rec->max_direction = bit_unpack(buf, pos, hd.direction_bits);
6505 pos += hd.direction_bits;
6507 rec->flood_begins = signed_bit_unpack(buf, pos, hd.time_bits);
6508 pos += hd.time_bits;
6510 rec->ebb_begins = signed_bit_unpack(buf, pos, hd.time_bits);
6511 pos += hd.time_bits;
6519 rec->country = bit_unpack(buf, pos, hd.country_bits);
6520 pos += hd.country_bits;
6522 unpack_string(buf, bufsize, &pos, rec->source, ONELINER_LENGTH,
6525 rec->restriction = bit_unpack(buf, pos, hd.restriction_bits);
6526 pos += hd.restriction_bits;
6528 unpack_string(buf, bufsize, &pos, rec->comments, MONOLOGUE_LENGTH,
6530 unpack_string(buf, bufsize, &pos, rec->notes, MONOLOGUE_LENGTH,
6533 rec->legalese = bit_unpack(buf, pos, hd.legalese_bits);
6534 pos += hd.legalese_bits;
6536 unpack_string(buf, bufsize, &pos, rec->station_id_context,
6537 ONELINER_LENGTH,
"station_id_context field");
6538 unpack_string(buf, bufsize, &pos, rec->station_id, ONELINER_LENGTH,
6539 "station_id field");
6541 rec->date_imported = bit_unpack(buf, pos, hd.date_bits);
6542 pos += hd.date_bits;
6544 unpack_string(buf, bufsize, &pos, rec->xfields, MONOLOGUE_LENGTH,
6547 rec->direction_units = bit_unpack(buf, pos, hd.dir_unit_bits);
6548 pos += hd.dir_unit_bits;
6550 rec->min_direction = bit_unpack(buf, pos, hd.direction_bits);
6551 pos += hd.direction_bits;
6553 rec->max_direction = bit_unpack(buf, pos, hd.direction_bits);
6554 pos += hd.direction_bits;
6556 rec->level_units = bit_unpack(buf, pos, hd.level_unit_bits);
6558 rec->units = rec->level_units;
6560 pos += hd.level_unit_bits;
6562 if (rec->header.record_type == REFERENCE_STATION) {
6563 temp_int = signed_bit_unpack(buf, pos, hd.datum_offset_bits);
6564 rec->datum_offset = (NV_FLOAT32)temp_int / hd.datum_offset_scale;
6565 pos += hd.datum_offset_bits;
6567 rec->datum = bit_unpack(buf, pos, hd.datum_bits);
6568 pos += hd.datum_bits;
6570 rec->zone_offset = signed_bit_unpack(buf, pos, hd.time_bits);
6571 pos += hd.time_bits;
6573 rec->expiration_date = bit_unpack(buf, pos, hd.date_bits);
6574 pos += hd.date_bits;
6576 rec->months_on_station =
6577 bit_unpack(buf, pos, hd.months_on_station_bits);
6578 pos += hd.months_on_station_bits;
6580 rec->last_date_on_station = bit_unpack(buf, pos, hd.date_bits);
6581 pos += hd.date_bits;
6583 rec->confidence = bit_unpack(buf, pos, hd.confidence_value_bits);
6584 pos += hd.confidence_value_bits;
6586 for (i = 0; i < hd.pub.constituents; ++i) {
6587 rec->amplitude[i] = 0.0;
6588 rec->epoch[i] = 0.0;
6591 count = bit_unpack(buf, pos, hd.constituent_bits);
6592 pos += hd.constituent_bits;
6594 for (i = 0; i < count; ++i) {
6595 j = bit_unpack(buf, pos, hd.constituent_bits);
6596 pos += hd.constituent_bits;
6599 (NV_FLOAT32)bit_unpack(buf, pos, hd.amplitude_bits) /
6601 pos += hd.amplitude_bits;
6604 (NV_FLOAT32)bit_unpack(buf, pos, hd.epoch_bits) / hd.epoch_scale;
6605 pos += hd.epoch_bits;
6607 }
else if (rec->header.record_type == SUBORDINATE_STATION) {
6608 rec->min_time_add = signed_bit_unpack(buf, pos, hd.time_bits);
6609 pos += hd.time_bits;
6611 temp_int = signed_bit_unpack(buf, pos, hd.level_add_bits);
6612 rec->min_level_add = (NV_FLOAT32)temp_int / hd.level_add_scale;
6613 pos += hd.level_add_bits;
6616 temp_int = bit_unpack(buf, pos, hd.level_multiply_bits);
6617 rec->min_level_multiply =
6618 (NV_FLOAT32)temp_int / hd.level_multiply_scale;
6619 pos += hd.level_multiply_bits;
6621 rec->max_time_add = signed_bit_unpack(buf, pos, hd.time_bits);
6622 pos += hd.time_bits;
6624 temp_int = signed_bit_unpack(buf, pos, hd.level_add_bits);
6625 rec->max_level_add = (NV_FLOAT32)temp_int / hd.level_add_scale;
6626 pos += hd.level_add_bits;
6629 temp_int = bit_unpack(buf, pos, hd.level_multiply_bits);
6630 rec->max_level_multiply =
6631 (NV_FLOAT32)temp_int / hd.level_multiply_scale;
6632 pos += hd.level_multiply_bits;
6634 rec->flood_begins = signed_bit_unpack(buf, pos, hd.time_bits);
6635 pos += hd.time_bits;
6637 rec->ebb_begins = signed_bit_unpack(buf, pos, hd.time_bits);
6638 pos += hd.time_bits;
6648 assert(pos <= bufsize * 8);
6672 NV_INT32 read_tide_record(NV_INT32 num,
TIDE_RECORD *rec) {
6678 "libtcd error: attempt to access database when database not open\n");
6682 if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
return -1;
6685 bufsize = tindex[num].record_size;
6686 if ((buf = (NV_U_BYTE *)calloc(bufsize,
sizeof(NV_U_BYTE))) == NULL) {
6687 perror(
"Allocating read_tide_record buffer");
6691 current_record = num;
6692 require(fseek(fp, tindex[num].address, SEEK_SET) == 0);
6693 chk_fread(buf, tindex[num].record_size, 1, fp);
6694 unpack_tide_record(buf, bufsize, rec);
6721 "libtcd error: attempt to access database when database not open\n");
6726 if (!check_tide_record(rec))
return NVFalse;
6728 fseek(fp, hd.end_of_file, SEEK_SET);
6732 rec->header.record_number = hd.pub.number_of_records++;
6734 if (write_tide_record(-1, rec)) {
6736 tindex, hd.pub.number_of_records *
sizeof(
TIDE_INDEX))) == NULL) {
6737 perror(
"Allocating more index records");
6741 tindex[rec->header.record_number].address = pos;
6742 tindex[rec->header.record_number].record_size = rec->header.record_size;
6743 tindex[rec->header.record_number].record_type = rec->header.record_type;
6744 tindex[rec->header.record_number].reference_station =
6745 rec->header.reference_station;
6746 assert(rec->header.tzfile >= 0);
6747 tindex[rec->header.record_number].tzfile = rec->header.tzfile;
6748 tindex[rec->header.record_number].lat =
6749 NINT(rec->header.latitude * hd.latitude_scale);
6750 tindex[rec->header.record_number].lon =
6751 NINT(rec->header.longitude * hd.longitude_scale);
6753 if ((tindex[rec->header.record_number].name = (NV_CHAR *)calloc(
6754 strlen(rec->header.name) + 1,
sizeof(NV_CHAR))) == NULL) {
6755 perror(
"Allocating index name memory");
6759 strcpy(tindex[rec->header.record_number].name, rec->header.name);
6762 hd.end_of_file = pos;
6766 if (db) *db = hd.pub;
6795 NV_INT32 i, newrecnum, *map;
6796 NV_U_BYTE **allrecs_packed;
6799 LOG_ERROR (
"libtcd error: attempt to access database when database not open\n");
6804 if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
return NVFalse;
6808 if (!(map = (NV_INT32 *) malloc (hd.pub.number_of_records *
sizeof(NV_INT32)))) {
6809 perror (
"libtcd: delete_tide_record: can't malloc");
6812 if (!(allrecs_packed = (NV_U_BYTE **) malloc (hd.pub.number_of_records *
sizeof(NV_U_BYTE*)))) {
6813 perror (
"libtcd: delete_tide_record: can't malloc");
6821 require (fseek (fp, tindex[0].address, SEEK_SET) == 0);
6822 for (newrecnum=0,i=0; i<(NV_INT32)hd.pub.number_of_records; ++i) {
6823 assert (ftell(fp) == tindex[i].address);
6824 if (i == num || (tindex[i].record_type == SUBORDINATE_STATION && tindex[i].reference_station == num)) {
6826 allrecs_packed[i] = NULL;
6827 require (fseek (fp, tindex[i].record_size, SEEK_CUR) == 0);
6829 map[i] = newrecnum++;
6830 if (!(allrecs_packed[i] = (NV_U_BYTE *) malloc (tindex[i].record_size))) {
6831 perror (
"libtcd: delete_tide_record: can't malloc");
6832 for (--i; i>=0; --i)
6833 free (allrecs_packed[i]);
6834 free (allrecs_packed);
6838 chk_fread (allrecs_packed[i], tindex[i].record_size, 1, fp);
6844 require (fseek (fp, tindex[0].address, SEEK_SET) == 0);
6845 require (ftruncate (fileno(fp), tindex[0].address) == 0);
6847 for (i=0; i<(NV_INT32)hd.pub.number_of_records; ++i)
6849 if (tindex[i].record_type == SUBORDINATE_STATION) {
6850 assert (tindex[i].reference_station >= 0);
6851 assert (tindex[i].reference_station <= (NV_INT32)hd.pub.number_of_records);
6852 if (map[tindex[i].reference_station] != tindex[i].reference_station) {
6855 unpack_tide_record (allrecs_packed[i], tindex[i].record_size, &rec);
6856 free (allrecs_packed[i]);
6857 rec.header.reference_station = map[tindex[i].reference_station];
6858 pack_tide_record (&rec, &(allrecs_packed[i]), &(tindex[i].record_size));
6861 chk_fwrite (allrecs_packed[i], tindex[i].record_size, 1, fp);
6862 free (allrecs_packed[i]);
6867 free (allrecs_packed);
6873 hd.end_of_file = ftell(fp);
6874 hd.pub.number_of_records = newrecnum;
6877 open_tide_db (filename);
6906 NV_BOOL update_tide_record(NV_INT32 num,
TIDE_RECORD *rec)
6913 NV_U_BYTE *
block = NULL;
6917 "libtcd error: attempt to access database when database not open\n");
6922 if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
return NVFalse;
6924 if (!check_tide_record(rec))
return NVFalse;
6927 read_tide_record(num, &tmp_rec);
6928 if (rec->header.record_size != tmp_rec.header.record_size) {
6936 size = hd.end_of_file - pos;
6941 if ((
block = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
6942 perror(
"Allocating block");
6945 chk_fread(
block, size, 1, fp);
6949 write_tide_record(num, rec);
6953 chk_fwrite(
block, size, 1, fp);
6957 hd.end_of_file = ftell(fp);
6961 open_tide_db(filename);
6966 write_tide_record(num, rec);
6969 tindex[num].record_size = rec->header.record_size;
6970 tindex[num].record_type = rec->header.record_type;
6971 tindex[num].reference_station = rec->header.reference_station;
6972 tindex[num].tzfile = rec->header.tzfile;
6973 tindex[num].lat = NINT(rec->header.latitude * hd.latitude_scale);
6974 tindex[num].lon = NINT(rec->header.longitude * hd.longitude_scale);
6979 if (strcmp(tindex[num].name, rec->header.name) != 0) {
6980 free(tindex[num].name);
6982 (NV_CHAR *)calloc(strlen(rec->header.name) + 1,
sizeof(NV_CHAR));
6983 strcpy(tindex[num].name, rec->header.name);
6988 if (db) *db = hd.pub;
7025 NV_INT32 m2, s2, k1, o1;
7026 NV_FLOAT32 epoch_m2, epoch_s2, epoch_k1, epoch_o1;
7029 require((m2 = find_constituent(
"M2")) >= 0);
7030 require((s2 = find_constituent(
"S2")) >= 0);
7031 require((k1 = find_constituent(
"K1")) >= 0);
7032 require((o1 = find_constituent(
"O1")) >= 0);
7034 if (rec->amplitude[m2] == 0.0 || rec->amplitude[s2] == 0.0 ||
7035 rec->amplitude[k1] == 0.0 || rec->amplitude[o1] == 0.0)
7038 epoch_m2 = rec->epoch[m2];
7039 epoch_s2 = rec->epoch[s2];
7040 epoch_k1 = rec->epoch[k1];
7041 epoch_o1 = rec->epoch[o1];
7043 for (i = 0; i < hd.pub.constituents; ++i) {
7044 if (rec->amplitude[i] == 0.0 && rec->epoch[i] == 0.0) {
7045 for (j = 0; j < INFERRED_SEMI_DIURNAL_COUNT; ++j) {
7046 if (!strcmp(inferred_semi_diurnal[j], get_constituent(i))) {
7050 (semi_diurnal_coeff[j] / coeff[0]) * rec->amplitude[m2];
7052 if (fabs((NV_FLOAT64)(epoch_s2 - epoch_m2)) > 180.0) {
7053 if (epoch_s2 < epoch_m2) {
7059 rec->epoch[i] = epoch_m2 + ((hd.speed[i] - hd.speed[m2]) /
7060 (hd.speed[s2] - hd.speed[m2])) *
7061 (epoch_s2 - epoch_m2);
7065 for (j = 0; j < INFERRED_DIURNAL_COUNT; ++j) {
7066 if (!strcmp(inferred_diurnal[j], get_constituent(i))) {
7070 (diurnal_coeff[j] / coeff[1]) * rec->amplitude[o1];
7072 if (fabs((NV_FLOAT64)(epoch_k1 - epoch_o1)) > 180.0) {
7073 if (epoch_k1 < epoch_o1) {
7079 rec->epoch[i] = epoch_o1 + ((hd.speed[i] - hd.speed[o1]) /
7080 (hd.speed[k1] - hd.speed[o1])) *
7081 (epoch_k1 - epoch_o1);
7096 static NV_U_BYTE mask[8] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe},
7097 notmask[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
7136 NV_U_INT32 calculate_bits(NV_U_INT32 value) {
7137 NV_U_INT32 bits = 32;
7138 NV_U_INT32 theBit = 0x80000000;
7140 while (value < theBit) {
7175 void bit_pack(NV_U_BYTE buffer[], NV_U_INT32 start, NV_U_INT32 numbits,
7177 NV_INT32 start_byte, end_byte, start_bit, end_bit, i;
7179 i = start + numbits;
7185 start_byte = start >> 3;
7192 start_bit = start & 7;
7197 i = end_byte - start_byte - 1;
7201 if (start_byte == end_byte) {
7206 buffer[start_byte] &= mask[start_bit] | notmask[end_bit];
7212 buffer[start_byte] |=
7213 (value << (8 - end_bit)) & (notmask[start_bit] & mask[end_bit]);
7221 buffer[start_byte] &= mask[start_bit];
7229 buffer[start_byte++] |=
7230 (value >> (numbits - (8 - start_bit))) & notmask[start_bit];
7237 buffer[start_byte] &= 0;
7241 buffer[start_byte++] |= (value >> ((i << 3) + end_bit)) & 255;
7246 buffer[start_byte] &= notmask[end_bit];
7252 buffer[start_byte] |= (value << (8 - end_bit));
7282 NV_U_INT32 bit_unpack(NV_U_BYTE buffer[], NV_U_INT32 start,
7283 NV_U_INT32 numbits) {
7284 NV_INT32 start_byte, end_byte, start_bit, end_bit, i;
7287 i = start + numbits;
7293 start_byte = start >> 3;
7300 start_bit = start & 7;
7305 i = end_byte - start_byte - 1;
7309 if (start_byte == end_byte) {
7313 (NV_U_INT32)buffer[start_byte] & (notmask[start_bit] & mask[end_bit]);
7317 value >>= (8 - end_bit);
7326 value = (NV_U_INT32)(buffer[start_byte++] & notmask[start_bit])
7327 << (numbits - (8 - start_bit));
7334 value += (NV_U_INT32)buffer[start_byte++] << ((i << 3) + end_bit);
7339 if (mask[end_bit]) {
7340 value += (NV_U_INT32)(buffer[start_byte] & mask[end_bit]) >> (8 - end_bit);
7373 NV_INT32 signed_bit_unpack(NV_U_BYTE buffer[], NV_U_INT32 start,
7374 NV_U_INT32 numbits) {
7375 static NV_INT32 extend_mask = 0x7fffffff;
7379 assert(numbits > 0);
7381 value = bit_unpack(buffer, start, numbits);
7383 if (value & (1 << (numbits - 1))) value |= (extend_mask << numbits);
General purpose GUI support.
Runtime representation of a plugin block.