28#include <wx/hashmap.h>
50static time_t s_next_epoch = TIDE_BAD_TIME;
51static time_t s_this_epoch = TIDE_BAD_TIME;
52static int s_this_year = -1;
54static double time2dt_tide(time_t t,
int deriv,
IDX_entry *pIDX);
55static int yearoftimet(time_t t);
56static void happy_new_year(
IDX_entry *pIDX,
int new_year);
57static void set_epoch(
IDX_entry *pIDX,
int year);
59static double time2tide(time_t t,
IDX_entry *pIDX) {
60 return time2dt_tide(t, 0, pIDX);
70 if (!pmsd->have_BOGUS)
81double time2atide(time_t t,
IDX_entry *pIDX) {
93int next_big_event(time_t *tm,
IDX_entry *pIDX) {
95 int flags = 0, slope = 0;
96 p = time2atide(*tm, pIDX);
98 q = time2atide(*tm, pIDX);
100 if (p < q) slope = 1;
102 if ((slope == 1 && q < p) || (slope == 0 && p < q)) {
104 flags |= (1 << slope);
118 if ((p > marklev && q <= marklev) || (p < marklev && q >= marklev)) {
134 q = time2atide(*tm, pIDX);
135 if ((slope == 1 && q < p) || (slope == 0 && p < q)) {
137 flags |= (1 << slope);
149 if (flags < 4) *tm -= 60;
153 q = time2atide(*tm, pIDX);
162double time2mean(time_t t,
IDX_entry *pIDX) {
165 int new_year = yearoftimet(t);
166 if (pIDX->
epoch_year != new_year) happy_new_year(pIDX, new_year);
168 for (a = 0; a < pIDX->
num_csts; a++) {
185double time2asecondary(time_t t,
IDX_entry *pIDX) {
189 if (!(pIDX->
have_offsets))
return time2atide(tadj, pIDX);
196#define intervalwidth 15
197#define stretchfactor 3
199 static time_t lowtime = 0, hightime = 0;
200 static double lowlvl, highlvl;
202 double S, Z, HI, HS, magicnum;
203 time_t interval = 3600 * intervalwidth;
204 long difflow, diffhigh;
205 int badlowflag = 0, badhighflag = 0;
220 Z = time2mean(T, pIDX);
221 S = time2tide(T, pIDX) - Z;
243 difflow = T - lowtime;
245 difflow = lowtime - T;
247 diffhigh = T - hightime;
249 diffhigh = hightime - T;
252 if (difflow > interval * stretchfactor) badlowflag = 1;
253 if (badlowflag || (difflow > interval && S > 0)) {
257 next_big_event(&tt, pIDX);
258 lowlvl = time2tide(tt, pIDX);
260 while (tt < T + interval) {
261 next_big_event(&tt, pIDX);
262 tl = time2tide(tt, pIDX);
263 if (tl < lowlvl && tt < T + interval) {
270 if (diffhigh > interval * stretchfactor) badhighflag = 1;
271 if (badhighflag || (diffhigh > interval && S < 0)) {
275 next_big_event(&tt, pIDX);
276 highlvl = time2tide(tt, pIDX);
278 while (tt < T + interval) {
279 next_big_event(&tt, pIDX);
280 tl = time2tide(tt, pIDX);
281 if (tl > highlvl && tt < T + interval) {
301 magicnum = 0.5 * S / fabs(highlvl - Z);
303 magicnum = 0.5 * S / fabs(lowlvl - Z);
307 HI = time2tide(T, pIDX);
310 double ht_off, lt_off;
323 double RH = 1.0, RL = 1.0, HH = 0.0, HL = 0.0;
332 HS = HI * ((RH + RL) / 2 + (RH - RL) * magicnum) + (HH + HL) / 2 +
333 (HH - HL) * magicnum;
387double _time2dt_tide(time_t t,
int deriv,
IDX_entry *pIDX) {
388 double dt_tide = 0.0;
392 tempd = M_PI / 2.0 * deriv;
393 for (a = 0; a < pIDX->
num_csts; a++) {
400 for (b = deriv; b > 0; b--) term *= pIDX->
m_cst_speeds[a];
423static double blend_weight(
double x,
int deriv) {
426 if (x2 >= 1.0)
return deriv == 0 && x > 0.0 ? 1.0 : 0.0;
430 return ((3.0 * x2 - 10.0) * x2 + 15.0) * x / 16.0 + 0.5;
432 return ((x2 - 2.0) * x2 + 1.0) * (15.0 / 16.0);
434 return (x2 - 1.0) * x * (15.0 / 4.0);
443double blend_tide(time_t t,
unsigned int deriv,
int first_year,
double blend,
445 double fl[TIDE_MAX_DERIV + 1];
446 double fr[TIDE_MAX_DERIV + 1];
448 double w[TIDE_MAX_DERIV + 1];
457 int year = yearoftimet(t);
458 if (year == first_year + 1)
460 else if (year != first_year)
461 happy_new_year(pIDX, first_year);
462 for (n = 0; n <= deriv; n++) fp[n] = _time2dt_tide(t, n, pIDX);
469 happy_new_year(pIDX, first_year + 1);
472 happy_new_year(pIDX, first_year);
475 for (n = 0; n <= deriv; n++) {
476 fp[n] = _time2dt_tide(t, n, pIDX);
477 w[n] = blend_weight(blend, n);
485 for (n = 0; n <= deriv; n++) {
486 f += fact * w[n] * (fr[deriv - n] - fl[deriv - n]);
487 fact *= (double)(deriv - n) / (n + 1) * (1.0 / TIDE_BLEND_TIME);
489 printf(
" %ld %g %g %g %g\n", (
long)t, blend, fr[0], fl[0], f);
493static double time2dt_tide(time_t t,
int deriv,
IDX_entry *pIDX) {
495 int yott = yearoftimet(t);
499 if (new_year != s_this_year) {
501 set_epoch(pIDX, new_year + 1);
502 s_next_epoch = pIDX->
epoch;
504 s_next_epoch = TIDE_BAD_TIME;
506 happy_new_year(pIDX, s_this_year = new_year);
507 s_this_epoch = pIDX->
epoch;
514 if (t - s_this_epoch <= TIDE_BLEND_TIME && s_this_year > pIDX->
first_year)
515 return blend_tide(t, deriv, s_this_year - 1,
516 (
double)(t - s_this_epoch) / TIDE_BLEND_TIME, pIDX);
517 else if (s_next_epoch - t <= TIDE_BLEND_TIME &&
519 return blend_tide(t, deriv, s_this_year,
520 -(
double)(s_next_epoch - t) / TIDE_BLEND_TIME, pIDX);
525 if (pIDX->
epoch_year != new_year) happy_new_year(pIDX, new_year);
527 return _time2dt_tide(t, deriv, pIDX);
532void figure_max_amplitude(
IDX_entry *pIDX) {
537 double year_amp = 0.0;
539 for (a = 0; a < pIDX->
num_csts; a++)
547void figure_multipliers(
IDX_entry *pIDX,
int year) {
550 figure_max_amplitude(pIDX);
551 for (a = 0; a < pIDX->
num_csts; a++) {
559#define compare_int(a, b) (((int)(a)) - ((int)(b)))
560int compare_tm(
struct tm *a,
struct tm *b) {
568 temp = compare_int(a->tm_year, b->tm_year);
569 if (temp)
return temp;
570 temp = compare_int(a->tm_mon, b->tm_mon);
571 if (temp)
return temp;
572 temp = compare_int(a->tm_mday, b->tm_mday);
573 if (temp)
return temp;
574 temp = compare_int(a->tm_hour, b->tm_hour);
575 if (temp)
return temp;
576 temp = compare_int(a->tm_min, b->tm_min);
577 if (temp)
return temp;
578 return compare_int(a->tm_sec, b->tm_sec);
584time_t tm2gmt(
struct tm *ht) {
585 time_t guess, newguess, thebit;
586 int loopcounter, compare;
590 loopcounter = (
sizeof(time_t) * 8) - 1;
591 thebit = ((time_t)1) << (loopcounter - 1);
596 if ((
signed long)thebit < (time_t)(0)) {
599 thebit = ((time_t)1) << (loopcounter - 1);
602 for (; loopcounter; loopcounter--) {
603 newguess = guess | thebit;
604 gt = gmtime(&newguess);
606 compare = compare_tm(gt, ht);
607 if (compare <= 0) guess = newguess;
615static int yearoftimet(time_t t) {
return ((gmtime(&t))->tm_year) + 1900; }
618static void set_epoch(
IDX_entry *pIDX,
int year) {
621 ht.tm_year = year - 1900;
622 ht.tm_sec = ht.tm_min = ht.tm_hour = ht.tm_mon = 0;
624 pIDX->
epoch = tm2gmt(&ht);
628static void happy_new_year(
IDX_entry *pIDX,
int new_year) {
630 figure_multipliers(pIDX, new_year);
631 set_epoch(pIDX, new_year);
637TCMgr::~TCMgr() { PurgeData(); }
639void TCMgr::PurgeData() {
640 m_Combined_IDX_array.clear();
643 m_source_array.Clear();
646TC_Error_Code TCMgr::LoadDataSources(std::vector<std::string> &sources) {
650 m_sourcefile_array.clear();
651 m_sourcefile_array = sources;
655 for (
auto src : sources) {
657 TC_Error_Code r = s->LoadData(src);
658 if (r != TC_NO_ERROR) {
660 msg.Printf(
" Error loading Tide/Currect data source %s ", src.c_str());
661 if (r == TC_FILE_NOT_FOUND)
662 msg +=
"Error Code: TC_FILE_NOT_FOUND";
665 msg1.Printf(
"Error code: %d", r);
671 m_source_array.Add(s);
673 for (
int k = 0; k < s->GetMaxIndex(); k++) {
677 m_Combined_IDX_array.push_back(pIDX);
684 if (m_Combined_IDX_array.empty())
686 NULL, _(
"It seems you have no tide/current harmonic data installed."),
687 _(
"OpenCPN Info"), wxOK | wxCENTER);
689 ScrubCurrentDepths();
693void TCMgr::ScrubCurrentDepths() {
698 WX_DECLARE_STRING_HASH_MAP(
int, currentDepth_index_hash);
700 currentDepth_index_hash hash1;
702 for (
int i = 1; i < Get_max_IDX() + 1; i++) {
717 currentDepth_index_hash::iterator it = hash1.find(key1);
718 if (it == hash1.end()) {
727 if (depth_a < depth_b) {
739const IDX_entry *TCMgr::GetIDX_entry(
int index)
const {
740 if ((
unsigned int)index < m_Combined_IDX_array.size())
741 return m_Combined_IDX_array[index];
746bool TCMgr::GetTideOrCurrent(time_t t,
int idx,
float &tcvalue,
float &dir) {
752 IDX_entry *pIDX = m_Combined_IDX_array[idx];
767 if (pIDX->
pDataSource->LoadHarmonicData(pIDX) != TC_NO_ERROR)
return false;
771 int yott = yearoftimet(t);
773 happy_new_year(pIDX, yott);
777 double level = time2asecondary(t + (00 * 60), pIDX);
788bool TCMgr::GetTideOrCurrentMeters(time_t t,
int idx,
float &tcvalue,
790 float val_from_index;
791 bool bret = GetTideOrCurrent(t, idx, val_from_index, dir);
792 if (!bret)
return false;
795 IDX_entry *pIDX = m_Combined_IDX_array[idx];
799 int unit_c = TCDataFactory::findunit(pmsd->unit);
801 val_from_index *= TCDataFactory::known_units[unit_c].conv_factor;
803 tcvalue = val_from_index;
809extern wxDateTime gTimeSource;
811bool TCMgr::GetTideOrCurrent15(time_t t_d,
int idx,
float &tcvalue,
float &dir,
814 IDX_entry *pIDX = m_Combined_IDX_array[idx];
823 wxDateTime this_now = gTimeSource;
824 if (this_now.IsValid() ==
false) this_now = wxDateTime::Now();
825 wxDateTime this_gmt = this_now.ToGMT();
826 wxTimeSpan diff = this_gmt.Subtract(this_now);
827 int diff_mins = diff.GetMinutes();
830 if (this_now.IsDST()) station_offset += 60;
831 int corr_mins = station_offset - diff_mins;
833 wxDateTime today_00 = this_now;
834 today_00.ResetTime();
835 int t_today_00 = today_00.GetTicks();
836 int t_today_00_at_station = t_today_00 - (corr_mins * 60);
839 this_gmt.GetTicks() - (station_offset * 60) + (corr_mins * 60);
841 int t_mins = (t_at_station - t_today_00_at_station) / 60;
842 int t_15s = t_mins / 15;
846 int tref1 = t_today_00_at_station + t_15s * 15 * 60;
853 int tref = t_today_00_at_station + t_15s * 15 * 60;
854 ret = GetTideOrCurrent(tref, idx, tcvalue, dir);
859 pIDX->
Ret15 = !(ret == 0);
867 int tref = t_today_00_at_station + t_15s * 15 * 60;
868 ret = GetTideOrCurrent(tref, idx, tcvalue, dir);
873 pIDX->
Ret15 = !(ret == 0);
880bool TCMgr::GetTideFlowSens(time_t t,
int sch_step,
int idx,
float &tcvalue_now,
881 float &tcvalue_prev,
bool &w_t) {
888 IDX_entry *pIDX = m_Combined_IDX_array[idx];
890 if (!pIDX)
return false;
895 if (pIDX->
pDataSource->LoadHarmonicData(pIDX) != TC_NO_ERROR)
return false;
899 int yott = yearoftimet(t);
900 happy_new_year(pIDX, yott);
904 tcvalue_now = time2asecondary(t, pIDX);
905 tcvalue_prev = time2asecondary(t + sch_step, pIDX);
908 tcvalue_now > tcvalue_prev;
913void TCMgr::GetHightOrLowTide(time_t t,
int sch_step_1,
int sch_step_2,
914 float tide_val,
bool w_t,
int idx,
float &tcvalue,
921 IDX_entry *pIDX = m_Combined_IDX_array[idx];
928 if (pIDX->
pDataSource->LoadHarmonicData(pIDX) != TC_NO_ERROR)
return;
944 int yott = yearoftimet(t);
945 happy_new_year(pIDX, yott);
948 double newval = tide_val;
949 double oldval = (w_t) ? newval - 1 : newval + 1;
953 while ((newval > oldval) == w_t)
957 ttt = t + (sch_step_1 * j);
958 newval = time2asecondary(ttt, pIDX);
960 oldval = (w_t) ? newval - 1 : newval + 1;
961 while ((newval > oldval) == w_t)
965 ttt = t + (sch_step_1 * j) - (sch_step_2 * k);
966 newval = time2asecondary(ttt, pIDX);
969 tctime = ttt + sch_step_2;
988int TCMgr::GetNextBigEvent(time_t *tm,
int idx) {
993 int flags = 0, slope = 0;
994 ret = GetTideOrCurrent(*tm, idx, tcvalue[0], dir);
997 ret = GetTideOrCurrent(*tm, idx, tcvalue[0], dir);
1000 if (p < q) slope = 1;
1002 if ((slope == 1 && q < p) || (slope == 0 && p < q)) {
1004 flags |= (1 << slope);
1008 if (flags < 4) *tm -= 60;
1012 ret = GetTideOrCurrent(*tm, idx, tcvalue[0], dir);
1019std::wstring TCMgr::GetTidalEventStr(
int station_id, wxDateTime ref_dt,
1020 double lat,
double lon,
int dt_type) {
1022 time_t dtmtt = ref_dt.FromUTC().GetTicks();
1023 int event = GetNextBigEvent(&dtmtt, station_id);
1024 wxDateTime event_dt = wxDateTime(dtmtt).MakeUTC();
1026 std::wstring event_str;
1028 event_str = _(
"LW").ToStdWstring();
1029 }
else if (event == 2) {
1030 event_str = _(
"HW").ToStdWstring();
1032 event_str = _(
"Unavailable").ToStdWstring();
1036 event_str.append(L
": ");
1038 toUsrDateTime(event_dt, dt_type, lon).FormatISOCombined(
' '));
1044std::map<double, const IDX_entry *> TCMgr::GetStationsForLL(
double xlat,
1045 double xlon)
const {
1046 std::map<double, const IDX_entry *> x;
1049 for (
int j = 1; j < Get_max_IDX() + 1; j++) {
1050 lpIDX = GetIDX_entry(j);
1054 if (type ==
't' || type ==
'T') {
1056 DistanceBearingMercator(xlat, xlon, lpIDX->
IDX_lat, lpIDX->
IDX_lon, &brg,
1058 x.emplace(std::make_pair(dist, lpIDX));
1065int TCMgr::GetStationIDXbyName(
const wxString &prefix,
double xlat,
1066 double xlon)
const {
1070 double distx = 100000.;
1072 int jmax = Get_max_IDX();
1074 for (
int j = 1; j < Get_max_IDX() + 1; j++) {
1075 lpIDX = GetIDX_entry(j);
1079 if (((type ==
't') || (type ==
'T'))
1080 && (locnx.StartsWith(prefix))) {
1082 DistanceBearingMercator(xlat, xlon, lpIDX->
IDX_lat, lpIDX->
IDX_lon, &brg,
1094int TCMgr::GetStationIDXbyNameType(
const wxString &prefix,
double xlat,
1095 double xlon,
char type)
const {
1099 double distx = 100000.;
1103 int jmax = Get_max_IDX();
1105 for (
int j = 1; j < Get_max_IDX() + 1; j++) {
1106 lpIDX = GetIDX_entry(j);
1110 if ((type == typep) && (locnx.StartsWith(prefix))) {
1112 DistanceBearingMercator(xlat, xlon, lpIDX->
IDX_lat, lpIDX->
IDX_lon, &brg,
1138#define DEFAULT_HEADER_SIZE 4096
1139#define DEFAULT_NUMBER_OF_RECORDS 0
1140#define DEFAULT_LEVEL_UNIT_TYPES 5
1141#define DEFAULT_DIR_UNIT_TYPES 3
1142#define DEFAULT_RESTRICTION_TYPES 2
1143#define DEFAULT_RESTRICTION_BITS 4
1144#define DEFAULT_TZFILES 406
1145#define DEFAULT_TZFILE_BITS 10
1146#define DEFAULT_COUNTRIES 240
1147#define DEFAULT_COUNTRY_BITS 9
1148#define DEFAULT_DATUM_TYPES 61
1149#define DEFAULT_DATUM_BITS 7
1150#define DEFAULT_LEGALESES 1
1151#define DEFAULT_LEGALESE_BITS 4
1152#define DEFAULT_SPEED_SCALE 10000000
1153#define DEFAULT_EQUILIBRIUM_SCALE 100
1154#define DEFAULT_NODE_SCALE 10000
1155#define DEFAULT_AMPLITUDE_BITS 19
1156#define DEFAULT_AMPLITUDE_SCALE 10000
1157#define DEFAULT_EPOCH_BITS 16
1158#define DEFAULT_EPOCH_SCALE 100
1159#define DEFAULT_RECORD_TYPE_BITS 4
1160#define DEFAULT_LATITUDE_BITS 25
1161#define DEFAULT_LATITUDE_SCALE 100000
1162#define DEFAULT_LONGITUDE_BITS 26
1163#define DEFAULT_LONGITUDE_SCALE 100000
1164#define DEFAULT_RECORD_SIZE_BITS 16
1165#define DEFAULT_STATION_BITS 18
1166#define DEFAULT_DATUM_OFFSET_BITS 28
1167#define DEFAULT_DATUM_OFFSET_SCALE 10000
1168#define DEFAULT_DATE_BITS 27
1169#define DEFAULT_MONTHS_ON_STATION_BITS 10
1170#define DEFAULT_CONFIDENCE_VALUE_BITS 4
1171#define DEFAULT_NUMBER_OF_CONSTITUENTS_BITS 8
1172#define DEFAULT_TIME_BITS 13
1173#define DEFAULT_LEVEL_ADD_BITS 17
1174#define DEFAULT_LEVEL_ADD_SCALE 1000
1175#define DEFAULT_LEVEL_MULTIPLY_BITS 16
1176#define DEFAULT_LEVEL_MULTIPLY_SCALE 1000
1177#define DEFAULT_DIRECTION_BITS 9
1178#define DEFAULT_CONSTITUENT_SIZE 10
1179#define DEFAULT_LEVEL_UNIT_SIZE 15
1180#define DEFAULT_DIR_UNIT_SIZE 15
1181#define DEFAULT_RESTRICTION_SIZE 30
1182#define DEFAULT_DATUM_SIZE 70
1183#define DEFAULT_LEGALESE_SIZE 70
1184#define DEFAULT_TZFILE_SIZE 30
1185#define DEFAULT_COUNTRY_SIZE 50
1189#define INFERRED_SEMI_DIURNAL_COUNT 10
1190#define INFERRED_DIURNAL_COUNT 10
1193#pragma warning(disable : 4305)
1196const NV_CHAR *inferred_semi_diurnal[INFERRED_SEMI_DIURNAL_COUNT] = {
1197 "N2",
"NU2",
"MU2",
"2N2",
"LDA2",
"T2",
"R2",
"L2",
"K2",
"KJ2"};
1198const NV_CHAR *inferred_diurnal[INFERRED_DIURNAL_COUNT] = {
1199 "OO1",
"M1",
"J1",
"RHO1",
"Q1",
"2Q1",
"P1",
"PI1",
"PHI1",
"PSI1"};
1200NV_FLOAT32 semi_diurnal_coeff[INFERRED_SEMI_DIURNAL_COUNT] = {
1201 .1759, .0341, .0219, .0235, .0066, .0248, .0035, .0251, .1151, .0064};
1202NV_FLOAT32 diurnal_coeff[INFERRED_DIURNAL_COUNT] = {
1203 .0163, .0209, .0297, .0142, .0730, .0097, .1755, .0103, .0076, .0042};
1207NV_FLOAT32 coeff[2] = {.9085, .3771};
1217NV_CHAR level_unit[DEFAULT_LEVEL_UNIT_TYPES][DEFAULT_LEVEL_UNIT_SIZE] = {
1218 "Unknown",
"feet",
"meters",
"knots",
"knots^2"};
1222NV_CHAR dir_unit[DEFAULT_DIR_UNIT_TYPES][DEFAULT_DIR_UNIT_SIZE] = {
1223 "Unknown",
"degrees true",
"degrees"};
1227NV_CHAR restriction[DEFAULT_RESTRICTION_TYPES][DEFAULT_RESTRICTION_SIZE] = {
1228 "Public Domain",
"DoD/DoD Contractors Only"};
1232NV_CHAR legalese[DEFAULT_LEGALESES][DEFAULT_LEGALESE_SIZE] = {
"NULL"};
1236NV_CHAR datum[DEFAULT_DATUM_TYPES][DEFAULT_DATUM_SIZE] = {
1240 "Mean Lower Low Water",
1242 "Mean Higher High Water",
1243 "Mean Lower High Water",
1244 "Mean Higher Low Water",
1245 "Mean Low Water Springs",
1246 "Mean Lower Low Water Springs",
1247 "Mean Low Water Neaps",
1248 "Mean High Water Neaps",
1249 "Mean High Water Springs",
1250 "Mean Higher High Water Springs",
1251 "Indian Spring Low Water",
1252 "Equatorial Spring Low Water",
1253 "Lowest Normal Low Water",
1255 "Lowest Possible Low Water",
1256 "Lowest Astronomical Tide",
1257 "International Great Lakes Datum(1955)",
1258 "Lower Low Water, Large Tide",
1259 "Lowest Normal Tide",
1260 "Higher High Water, Large Tide",
1262 "Higher High Water, Mean Tide",
1263 "Lower Low Water, Mean Tide",
1265 "World Geodetic System (1984)",
1266 "National Geodetic Vertical Datum",
1267 "Gulf Coast Low Water Datum",
1268 "Approximate Level of Mean Sea Level",
1269 "Approximate Level of Mean Low Water",
1270 "Approximate Level of Mean Lower Low Water",
1271 "Approximate Level of Mean High Water",
1272 "Approximate Level of Mean Higher High Water",
1273 "Approximate Level of Mean Lower High Water",
1274 "Approximate Level of Mean Higher Low Water",
1275 "Approximate Level of Mean Low Water Springs",
1276 "Approximate Level of Mean Lower Low Water Springs",
1277 "Approximate Level of Mean Low Water Neaps",
1278 "Approximate Level of Mean High Water Neaps",
1279 "Approximate Level of Mean High Water Springs",
1280 "Approximate Level of Mean Higher High Water Springs",
1281 "Approximate Level of Indian Spring Low Water",
1282 "Approximate Level of Equatorial Spring Low Water",
1283 "Approximate Level of Lowest Normal Low Water",
1284 "Approximate Level of Lowest Low Water",
1285 "Approximate Level of Lowest Possible Low Water",
1286 "Approximate Level of Lowest Astronomical Tide",
1287 "Approximate Level of International Great Lakes Datum (1955)",
1288 "Approximate Level of Lower Low Water, Large Tide",
1289 "Approximate Level of Lowest Normal Tide",
1290 "Approximate Level of Higher High Water, Large Tide",
1291 "Approximate Level of Mean Water Level",
1292 "Approximate Level of Higher High Water, Mean Tide",
1293 "Approximate Level of Lower Low Water, Mean Tide",
1294 "Approximate Level of Mean Tide Level",
1295 "Approximate Level of World Geodetic System (1984)",
1296 "Approximate Level of National Geodetic Vertical Datum",
1297 "Approximate Level of Gulf Coast Low Water Datum"};
1301NV_CHAR country[DEFAULT_COUNTRIES][DEFAULT_COUNTRY_SIZE] = {
1310 "Antigua & Barbuda",
1328 "Bosnia & Herzegovina",
1333 "British Indian Ocean Territory",
1343 "Central African Rep.",
1348 "Cocos (Keeling) Islands",
1351 "Congo (Dem. Rep.)",
1363 "Dominican Republic",
1368 "Equatorial Guinea",
1379 "French Southern & Antarctic Lands",
1396 "Heard Island & McDonald Islands",
1453 "Netherlands Antilles",
1461 "Northern Mariana Islands",
1484 "Sao Tome & Principe",
1495 "South Georgia & the South Sandwich Islands",
1501 "St Pierre & Miquelon",
1505 "Svalbard & Jan Mayen",
1517 "Trinidad & Tobago",
1521 "Turks & Caicos Is",
1525 "United Arab Emirates",
1528 "US minor outlying islands",
1534 "Virgin Islands (UK)",
1535 "Virgin Islands (US)",
1545NV_CHAR tzfile[DEFAULT_TZFILES][DEFAULT_TZFILE_SIZE] = {
1549 ":Africa/Addis_Ababa",
1557 ":Africa/Brazzaville",
1558 ":Africa/Bujumbura",
1560 ":Africa/Casablanca",
1564 ":Africa/Dar_es_Salaam",
1571 ":Africa/Johannesburg",
1577 ":Africa/Libreville",
1580 ":Africa/Lubumbashi",
1586 ":Africa/Mogadishu",
1591 ":Africa/Nouakchott",
1592 ":Africa/Ouagadougou",
1593 ":Africa/Porto-Novo",
1600 ":America/Anchorage",
1601 ":America/Anguilla",
1603 ":America/Araguaina",
1605 ":America/Asuncion",
1607 ":America/Barbados",
1610 ":America/Boa_Vista",
1613 ":America/Buenos_Aires",
1614 ":America/Cambridge_Bay",
1617 ":America/Catamarca",
1621 ":America/Chihuahua",
1623 ":America/Costa_Rica",
1626 ":America/Danmarkshavn",
1628 ":America/Dawson_Creek",
1631 ":America/Dominica",
1632 ":America/Edmonton",
1633 ":America/Eirunepe",
1634 ":America/El_Salvador",
1635 ":America/Ensenada",
1636 ":America/Fortaleza",
1637 ":America/Glace_Bay",
1639 ":America/Goose_Bay",
1640 ":America/Grand_Turk",
1642 ":America/Guadeloupe",
1643 ":America/Guatemala",
1644 ":America/Guayaquil",
1648 ":America/Hermosillo",
1649 ":America/Indiana/Knox",
1650 ":America/Indiana/Marengo",
1651 ":America/Indianapolis",
1652 ":America/Indiana/Vevay",
1658 ":America/Kentucky/Monticello",
1661 ":America/Los_Angeles",
1662 ":America/Louisville",
1666 ":America/Martinique",
1667 ":America/Mazatlan",
1669 ":America/Menominee",
1671 ":America/Mexico_City",
1672 ":America/Miquelon",
1673 ":America/Monterrey",
1674 ":America/Montevideo",
1675 ":America/Montreal",
1676 ":America/Montserrat",
1678 ":America/New_York",
1682 ":America/North_Dakota/Center",
1684 ":America/Pangnirtung",
1685 ":America/Paramaribo",
1687 ":America/Port-au-Prince",
1688 ":America/Port_of_Spain",
1689 ":America/Porto_Velho",
1690 ":America/Puerto_Rico",
1691 ":America/Rainy_River",
1692 ":America/Rankin_Inlet",
1695 ":America/Rio_Branco",
1696 ":America/Santiago",
1697 ":America/Santo_Domingo",
1698 ":America/Sao_Paulo",
1699 ":America/Scoresbysund",
1700 ":America/Shiprock",
1701 ":America/St_Johns",
1702 ":America/St_Kitts",
1703 ":America/St_Lucia",
1704 ":America/St_Thomas",
1705 ":America/St_Vincent",
1706 ":America/Swift_Current",
1707 ":America/Tegucigalpa",
1709 ":America/Thunder_Bay",
1712 ":America/Vancouver",
1713 ":America/Whitehorse",
1714 ":America/Winnipeg",
1716 ":America/Yellowknife",
1717 ":Antarctica/Casey",
1718 ":Antarctica/Davis",
1719 ":Antarctica/DumontDUrville",
1720 ":Antarctica/Mawson",
1721 ":Antarctica/McMurdo",
1722 ":Antarctica/Palmer",
1723 ":Antarctica/South_Pole",
1724 ":Antarctica/Syowa",
1725 ":Antarctica/Vostok",
1726 ":Arctic/Longyearbyen",
1763 ":Asia/Krasnoyarsk",
1764 ":Asia/Kuala_Lumpur",
1773 ":Asia/Novosibirsk",
1795 ":Asia/Ulaanbaatar",
1798 ":Asia/Vladivostok",
1800 ":Asia/Yekaterinburg",
1803 ":Atlantic/Bermuda",
1805 ":Atlantic/Cape_Verde",
1807 ":Atlantic/Jan_Mayen",
1808 ":Atlantic/Madeira",
1809 ":Atlantic/Reykjavik",
1810 ":Atlantic/South_Georgia",
1811 ":Atlantic/Stanley",
1812 ":Atlantic/St_Helena",
1813 ":Australia/Adelaide",
1814 ":Australia/Brisbane",
1815 ":Australia/Broken_Hill",
1816 ":Australia/Darwin",
1817 ":Australia/Hobart",
1818 ":Australia/Lindeman",
1819 ":Australia/Lord_Howe",
1820 ":Australia/Melbourne",
1822 ":Australia/Sydney",
1852 ":Europe/Amsterdam",
1858 ":Europe/Bratislava",
1860 ":Europe/Bucharest",
1863 ":Europe/Copenhagen",
1865 ":Europe/Gibraltar",
1868 ":Europe/Kaliningrad",
1871 ":Europe/Ljubljana",
1873 ":Europe/Luxembourg",
1885 ":Europe/San_Marino",
1887 ":Europe/Simferopol",
1890 ":Europe/Stockholm",
1900 ":Europe/Zaporozhye",
1902 ":Indian/Antananarivo",
1904 ":Indian/Christmas",
1907 ":Indian/Kerguelen",
1910 ":Indian/Mauritius",
1914 ":Pacific/Auckland",
1918 ":Pacific/Enderbury",
1921 ":Pacific/Funafuti",
1922 ":Pacific/Galapagos",
1924 ":Pacific/Guadalcanal",
1926 ":Pacific/Honolulu",
1927 ":Pacific/Johnston",
1928 ":Pacific/Kiritimati",
1930 ":Pacific/Kwajalein",
1932 ":Pacific/Marquesas",
1938 ":Pacific/Pago_Pago",
1940 ":Pacific/Pitcairn",
1942 ":Pacific/Port_Moresby",
1943 ":Pacific/Rarotonga",
1947 ":Pacific/Tongatapu",
1962#define require(expr) \
1965 require_expr = (int)(expr); \
1966 assert(require_expr); \
2286NV_U_INT32 calculate_bits(NV_U_INT32 value);
2287void bit_pack(NV_U_BYTE *, NV_U_INT32, NV_U_INT32, NV_INT32);
2288NV_U_INT32 bit_unpack(NV_U_BYTE *, NV_U_INT32, NV_U_INT32);
2289NV_INT32 signed_bit_unpack(NV_U_BYTE buffer[], NV_U_INT32 start,
2290 NV_U_INT32 numbits);
2296 NV_U_INT32 record_size;
2298 NV_INT32 reference_station;
2301 NV_U_BYTE record_type;
2305static FILE *fp = NULL;
2307static NV_BOOL modified = NVFalse;
2308static NV_INT32 current_record, current_index;
2309static NV_CHAR filename[MONOLOGUE_LENGTH];
2319static void chk_fread(
void *ptr,
size_t size,
size_t nmemb, FILE *stream) {
2321 ret = fread(ptr, size, nmemb, stream);
2325 throw std::runtime_error(
"tcmgr file read exception");
2329static void chk_fwrite(
const void *ptr,
size_t size,
size_t nmemb,
2332 ret = fwrite(ptr, size, nmemb, stream);
2337 throw std::runtime_error(
"tcmgr file read exception");
2364 LOG_ERROR(
"\n\nRecord number = %d\n", rec->header.record_number);
2365 LOG_ERROR(
"Record size = %u\n", rec->header.record_size);
2366 LOG_ERROR(
"Record type = %u\n", rec->header.record_type);
2367 LOG_ERROR(
"Latitude = %f\n", rec->header.latitude);
2368 LOG_ERROR(
"Longitude = %f\n", rec->header.longitude);
2369 LOG_ERROR(
"Reference station = %d\n", rec->header.reference_station);
2370 LOG_ERROR(
"Tzfile = %s\n", get_tzfile(rec->header.tzfile));
2371 LOG_ERROR(
"Name = %s\n", rec->header.name);
2373 LOG_ERROR(
"Country = %s\n", get_country(rec->country));
2374 LOG_ERROR(
"Source = %s\n", rec->source);
2375 LOG_ERROR(
"Restriction = %s\n", get_restriction(rec->restriction));
2376 LOG_ERROR(
"Comments = %s\n", rec->comments);
2377 LOG_ERROR(
"Notes = %s\n", rec->notes);
2378 LOG_ERROR(
"Legalese = %s\n", get_legalese(rec->legalese));
2379 LOG_ERROR(
"Station ID context = %s\n", rec->station_id_context);
2380 LOG_ERROR(
"Station ID = %s\n", rec->station_id);
2381 LOG_ERROR(
"Date imported = %d\n", rec->date_imported);
2382 LOG_ERROR(
"Xfields = %s\n", rec->xfields);
2384 LOG_ERROR(
"Direction units = %s\n", get_dir_units(rec->direction_units));
2385 LOG_ERROR(
"Min direction = %d\n", rec->min_direction);
2386 LOG_ERROR(
"Max direction = %d\n", rec->max_direction);
2387 LOG_ERROR(
"Level units = %s\n", get_level_units(rec->level_units));
2389 if (rec->header.record_type == REFERENCE_STATION) {
2390 LOG_ERROR(
"Datum offset = %f\n", rec->datum_offset);
2391 LOG_ERROR(
"Datum = %s\n", get_datum(rec->datum));
2392 LOG_ERROR(
"Zone offset = %d\n", rec->zone_offset);
2393 LOG_ERROR(
"Expiration date = %d\n", rec->expiration_date);
2394 LOG_ERROR(
"Months on station = %d\n", rec->months_on_station);
2395 LOG_ERROR(
"Last date on station = %d\n", rec->last_date_on_station);
2396 LOG_ERROR(
"Confidence = %d\n", rec->confidence);
2397 for (i = 0; i < hd.pub.constituents; ++i) {
2398 if (rec->amplitude[i] != 0.0 || rec->epoch[i] != 0.0) {
2399 LOG_ERROR(
"Amplitude[%d] = %f\n", i, rec->amplitude[i]);
2400 LOG_ERROR(
"Epoch[%d] = %f\n", i, rec->epoch[i]);
2405 else if (rec->header.record_type == SUBORDINATE_STATION) {
2406 LOG_ERROR(
"Min time add = %d\n", rec->min_time_add);
2407 LOG_ERROR(
"Min level add = %f\n", rec->min_level_add);
2408 LOG_ERROR(
"Min level multiply = %f\n", rec->min_level_multiply);
2409 LOG_ERROR(
"Max time add = %d\n", rec->max_time_add);
2410 LOG_ERROR(
"Max level add = %f\n", rec->max_level_add);
2411 LOG_ERROR(
"Max level multiply = %f\n", rec->max_level_multiply);
2412 LOG_ERROR(
"Flood begins = %d\n", rec->flood_begins);
2413 LOG_ERROR(
"Ebb begins = %d\n", rec->ebb_begins);
2426static void write_protect() {
2427 if (hd.pub.major_rev < LIBTCD_MAJOR_REV) {
2429 "libtcd error: can't modify TCD files created by earlier version. "
2430 "Use\nrewrite_tide_db to upgrade the TCD file.\n");
2454const NV_CHAR *get_country(NV_INT32 num) {
2457 "libtcd error: attempt to access database when database not open\n");
2460 if (num >= 0 && num < (NV_INT32)hd.pub.countries)
return (hd.country[num]);
2481const NV_CHAR *get_tzfile(NV_INT32 num) {
2484 "libtcd error: attempt to access database when database not open\n");
2487 if (num >= 0 && num < (NV_INT32)hd.pub.tzfiles)
return (hd.tzfile[num]);
2508const NV_CHAR *get_station(NV_INT32 num) {
2511 "libtcd error: attempt to access database when database not open\n");
2514 if (num >= 0 && num < (NV_INT32)hd.pub.number_of_records)
2515 return (tindex[num].name);
2537const NV_CHAR *get_constituent(NV_INT32 num) {
2540 "libtcd error: attempt to access database when database not open\n");
2543 if (num >= 0 && num < (NV_INT32)hd.pub.constituents)
2544 return (hd.constituent[num]);
2566const NV_CHAR *get_level_units(NV_INT32 num) {
2569 "libtcd error: attempt to access database when database not open\n");
2572 if (num >= 0 && num < (NV_INT32)hd.pub.level_unit_types)
2573 return (hd.level_unit[num]);
2595const NV_CHAR *get_dir_units(NV_INT32 num) {
2598 "libtcd error: attempt to access database when database not open\n");
2601 if (num >= 0 && num < (NV_INT32)hd.pub.dir_unit_types)
2602 return (hd.dir_unit[num]);
2624const NV_CHAR *get_restriction(NV_INT32 num) {
2627 "libtcd error: attempt to access database when database not open\n");
2630 if (num >= 0 && num < (NV_INT32)hd.pub.restriction_types)
2631 return (hd.restriction[num]);
2654NV_CHAR *get_pedigree(NV_INT32 num) {
return "Unknown"; }
2674const NV_CHAR *get_datum(NV_INT32 num) {
2677 "libtcd error: attempt to access database when database not open\n");
2680 if (num >= 0 && num < (NV_INT32)hd.pub.datum_types)
return (hd.datum[num]);
2687const NV_CHAR *get_legalese(NV_INT32 num) {
2690 "libtcd error: attempt to access database when database not open\n");
2693 if (num >= 0 && num < (NV_INT32)hd.pub.legaleses)
return (hd.legalese[num]);
2715NV_FLOAT64 get_speed(NV_INT32 num) {
2718 "libtcd error: attempt to access database when database not open\n");
2721 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents);
2722 return hd.speed[num];
2744NV_FLOAT32 get_equilibrium(NV_INT32 num, NV_INT32 year) {
2747 "libtcd error: attempt to access database when database not open\n");
2750 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 &&
2751 year < (NV_INT32)hd.pub.number_of_years);
2752 return hd.equilibrium[num][year];
2758NV_FLOAT32 *get_equilibriums(NV_INT32 num) {
2761 "libtcd error: attempt to access database when database not open\n");
2764 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents);
2765 return hd.equilibrium[num];
2787NV_FLOAT32 get_node_factor(NV_INT32 num, NV_INT32 year) {
2790 "libtcd error: attempt to access database when database not open\n");
2793 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 &&
2794 year < (NV_INT32)hd.pub.number_of_years);
2795 return hd.node_factor[num][year];
2801NV_FLOAT32 *get_node_factors(NV_INT32 num) {
2804 "libtcd error: attempt to access database when database not open\n");
2807 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents);
2808 return hd.node_factor[num];
2837 "libtcd error: attempt to access database when database not open\n");
2841 if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
return (NVFalse);
2845 rec->record_number = num;
2846 rec->record_size = tindex[num].record_size;
2847 rec->record_type = tindex[num].record_type;
2848 rec->latitude = (NV_FLOAT64)tindex[num].lat / hd.latitude_scale;
2849 rec->longitude = (NV_FLOAT64)tindex[num].lon / hd.longitude_scale;
2850 rec->reference_station = tindex[num].reference_station;
2851 rec->tzfile = tindex[num].tzfile;
2852 strcpy(rec->name, tindex[num].name);
2854 current_index = num;
2878 if (!get_partial_tide_record(current_index + 1, rec))
return (-1);
2880 return (current_index);
2903NV_INT32 get_nearest_partial_tide_record(NV_FLOAT64 lat, NV_FLOAT64 lon,
2905 NV_FLOAT64 diff, min_diff, lt, ln;
2906 NV_U_INT32 i, shortest = 0;
2908 min_diff = 999999999.9;
2909 for (i = 0; i < hd.pub.number_of_records; ++i) {
2910 lt = (NV_FLOAT64)tindex[i].lat / hd.latitude_scale;
2911 ln = (NV_FLOAT64)tindex[i].lon / hd.longitude_scale;
2913 diff = sqrt((lat - lt) * (lat - lt) + (lon - ln) * (lon - ln));
2915 if (diff < min_diff) {
2921 if (!get_partial_tide_record(shortest, rec))
return (-1);
2943NV_INT32 get_time(
const NV_CHAR *
string) {
2944 NV_INT32 hour, minute, hhmm;
2947 sscanf(
string,
"%d:%d", &hour, &minute);
2951 if (
string[0] ==
'-') {
2952 if (hour < 0) hour = -hour;
2954 hhmm = -(hour * 100 + minute);
2956 hhmm = hour * 100 + minute;
2980NV_CHAR *ret_time(NV_INT32 time) {
2981 NV_INT32 hour, minute;
2982 static NV_CHAR tname[16];
2984 hour = abs(time) / 100;
2985 assert(hour <= 99999 && hour >= -99999);
2986 minute = abs(time) % 100;
2989 sprintf(tname,
"-%02d:%02d", hour, minute);
2991 sprintf(tname,
"+%02d:%02d", hour, minute);
3000NV_CHAR *ret_time_neat(NV_INT32 time) {
3001 NV_INT32 hour, minute;
3002 static NV_CHAR tname[16];
3004 hour = abs(time) / 100;
3005 assert(hour <= 99999 && hour >= -99999);
3006 minute = abs(time) % 100;
3009 sprintf(tname,
"-%d:%02d", hour, minute);
3011 sprintf(tname,
"+%d:%02d", hour, minute);
3013 strcpy(tname,
"0:00");
3021NV_CHAR *ret_date(NV_U_INT32 date) {
3022 static NV_CHAR tname[30];
3024 strcpy(tname,
"NULL");
3031 sprintf(tname,
"%4u-%02u-%02u", y, m, d);
3055 "libtcd error: attempt to access database when database not open\n");
3065static void boundscheck_monologue(
const NV_CHAR *
string) {
3067 if (strlen(
string) >= MONOLOGUE_LENGTH) {
3081static void boundscheck_oneliner(
const NV_CHAR *
string) {
3083 if (strlen(
string) >= ONELINER_LENGTH) {
3111static NV_CHAR *clip_string(
const NV_CHAR *
string) {
3112 static NV_CHAR new_string[MONOLOGUE_LENGTH];
3113 NV_INT32 i, l, start = -1, end = -1;
3115 boundscheck_monologue(
string);
3116 new_string[0] =
'\0';
3118 l = (int)strlen(
string);
3120 for (i = 0; i < l; ++i) {
3121 if (
string[i] !=
' ') {
3126 for (i = l - 1; i >= start; --i) {
3127 if (
string[i] !=
' ' &&
string[i] != 10 &&
string[i] != 13) {
3132 if (start > -1 && end > -1 && end >= start) {
3133 strncpy(new_string,
string + start, end - start + 1);
3134 new_string[end - start + 1] =
'\0';
3161NV_INT32 search_station(
const NV_CHAR *
string) {
3162 static NV_CHAR last_search[ONELINER_LENGTH];
3163 static NV_U_INT32 j = 0;
3165 NV_CHAR name[ONELINER_LENGTH], search[ONELINER_LENGTH];
3169 "libtcd error: attempt to access database when database not open\n");
3173 boundscheck_oneliner(
string);
3175 for (i = 0; i < strlen(
string) + 1; ++i) search[i] =
tolower(
string[i]);
3177 if (strcmp(search, last_search)) j = 0;
3179 strcpy(last_search, search);
3181 while (j < hd.pub.number_of_records) {
3182 for (i = 0; i < strlen(tindex[j].name) + 1; ++i)
3183 name[i] =
tolower(tindex[j].name[i]);
3186 if (strstr(name, search))
return (j - 1);
3211NV_INT32 find_station(
const NV_CHAR *name) {
3216 "libtcd error: attempt to access database when database not open\n");
3221 for (i = 0; i < hd.pub.number_of_records; ++i) {
3222 if (!strcmp(name, tindex[i].name))
return (i);
3246NV_INT32 find_tzfile(
const NV_CHAR *name) {
3253 "libtcd error: attempt to access database when database not open\n");
3257 temp = clip_string(name);
3260 for (i = 0; i < hd.pub.tzfiles; ++i) {
3261 if (!strcmp(temp, get_tzfile(i))) {
3288NV_INT32 find_country(
const NV_CHAR *name) {
3295 "libtcd error: attempt to access database when database not open\n");
3299 temp = clip_string(name);
3302 for (i = 0; i < hd.pub.countries; ++i) {
3303 if (!strcmp(temp, get_country(i))) {
3330NV_INT32 find_level_units(
const NV_CHAR *name) {
3337 "libtcd error: attempt to access database when database not open\n");
3341 temp = clip_string(name);
3344 for (i = 0; i < hd.pub.level_unit_types; ++i) {
3345 if (!strcmp(get_level_units(i), temp)) {
3372NV_INT32 find_dir_units(
const NV_CHAR *name) {
3379 "libtcd error: attempt to access database when database not open\n");
3383 temp = clip_string(name);
3386 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
3387 if (!strcmp(get_dir_units(i), temp)) {
3415NV_INT32 find_pedigree(
const NV_CHAR *name) {
return 0; }
3436NV_INT32 find_datum(
const NV_CHAR *name) {
3443 "libtcd error: attempt to access database when database not open\n");
3447 temp = clip_string(name);
3450 for (i = 0; i < hd.pub.datum_types; ++i) {
3451 if (!strcmp(get_datum(i), temp)) {
3463NV_INT32 find_legalese(
const NV_CHAR *name) {
3470 "libtcd error: attempt to access database when database not open\n");
3474 temp = clip_string(name);
3477 for (i = 0; i < hd.pub.legaleses; ++i) {
3478 if (!strcmp(get_legalese(i), temp)) {
3506NV_INT32 find_constituent(
const NV_CHAR *name) {
3512 "libtcd error: attempt to access database when database not open\n");
3516 temp = clip_string(name);
3518 for (i = 0; i < hd.pub.constituents; ++i) {
3519 if (!strcmp(get_constituent(i), temp))
return (i);
3543NV_INT32 find_restriction(
const NV_CHAR *name) {
3550 "libtcd error: attempt to access database when database not open\n");
3554 temp = clip_string(name);
3557 for (i = 0; i < hd.pub.restriction_types; ++i) {
3558 if (!strcmp(get_restriction(i), temp)) {
3584void set_speed(NV_INT32 num, NV_FLOAT64 value) {
3587 "libtcd error: attempt to access database when database not open\n");
3591 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents);
3593 LOG_ERROR(
"libtcd set_speed: somebody tried to set a negative speed (%f)\n",
3597 hd.speed[num] = value;
3621void set_equilibrium(NV_INT32 num, NV_INT32 year, NV_FLOAT32 value) {
3624 "libtcd error: attempt to access database when database not open\n");
3628 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 &&
3629 year < (NV_INT32)hd.pub.number_of_years);
3630 hd.equilibrium[num][year] = value;
3654void set_node_factor(NV_INT32 num, NV_INT32 year, NV_FLOAT32 value) {
3657 "libtcd error: attempt to access database when database not open\n");
3661 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 &&
3662 year < (NV_INT32)hd.pub.number_of_years);
3665 "libtcd set_node_factor: somebody tried to set a negative or zero node "
3670 hd.node_factor[num][year] = value;
3721 "libtcd error: attempt to access database when database not open\n");
3727 if (strlen(name) + 1 > hd.tzfile_size) {
3728 LOG_ERROR(
"libtcd error: tzfile exceeds size limit (%u).\n",
3730 LOG_ERROR(
"The offending input is: %s\n", name);
3734 if (hd.pub.tzfiles == hd.max_tzfiles) {
3735 LOG_ERROR(
"You have exceeded the maximum number of tzfile types!\n");
3736 LOG_ERROR(
"You cannot add any new tzfile types.\n");
3737 LOG_ERROR(
"Modify the DEFAULT_TZFILE_BITS and rebuild the database.\n");
3741 c_name = clip_string(name);
3743 hd.tzfile[hd.pub.tzfiles] =
3744 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3746 if (hd.tzfile[hd.pub.tzfiles] == NULL) {
3747 perror(
"Allocating new tzfile string");
3751 strcpy(hd.tzfile[hd.pub.tzfiles++], c_name);
3752 if (db) *db = hd.pub;
3754 return (hd.pub.tzfiles - 1);
3780 "libtcd error: attempt to access database when database not open\n");
3786 if (strlen(name) + 1 > hd.country_size) {
3787 LOG_ERROR(
"libtcd error: country exceeds size limit (%u).\n",
3789 LOG_ERROR(
"The offending input is: %s\n", name);
3793 if (hd.pub.countries == hd.max_countries) {
3794 LOG_ERROR(
"You have exceeded the maximum number of country names!\n");
3795 LOG_ERROR(
"You cannot add any new country names.\n");
3796 LOG_ERROR(
"Modify the DEFAULT_COUNTRY_BITS and rebuild the database.\n");
3800 c_name = clip_string(name);
3802 hd.country[hd.pub.countries] =
3803 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3805 if (hd.country[hd.pub.countries] == NULL) {
3806 perror(
"Allocating new country string");
3810 strcpy(hd.country[hd.pub.countries++], c_name);
3811 if (db) *db = hd.pub;
3813 return (hd.pub.countries - 1);
3839 "libtcd error: attempt to access database when database not open\n");
3845 if (strlen(name) + 1 > hd.datum_size) {
3846 LOG_ERROR(
"libtcd error: datum exceeds size limit (%u).\n", hd.datum_size);
3847 LOG_ERROR(
"The offending input is: %s\n", name);
3851 if (hd.pub.datum_types == hd.max_datum_types) {
3852 LOG_ERROR(
"You have exceeded the maximum number of datum types!\n");
3853 LOG_ERROR(
"You cannot add any new datum types.\n");
3854 LOG_ERROR(
"Modify the DEFAULT_DATUM_BITS and rebuild the database.\n");
3858 c_name = clip_string(name);
3860 hd.datum[hd.pub.datum_types] =
3861 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3863 if (hd.datum[hd.pub.datum_types] == NULL) {
3864 perror(
"Allocating new datum string");
3868 strcpy(hd.datum[hd.pub.datum_types++], c_name);
3869 if (db) *db = hd.pub;
3871 return (hd.pub.datum_types - 1);
3882 "libtcd error: attempt to access database when database not open\n");
3888 if (strlen(name) + 1 > hd.legalese_size) {
3889 LOG_ERROR(
"libtcd error: legalese exceeds size limit (%u).\n",
3891 LOG_ERROR(
"The offending input is: %s\n", name);
3895 if (hd.pub.legaleses == hd.max_legaleses) {
3896 LOG_ERROR(
"You have exceeded the maximum number of legaleses!\n");
3897 LOG_ERROR(
"You cannot add any new legaleses.\n");
3898 LOG_ERROR(
"Modify the DEFAULT_LEGALESE_BITS and rebuild the database.\n");
3902 c_name = clip_string(name);
3904 hd.legalese[hd.pub.legaleses] =
3905 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3907 if (hd.legalese[hd.pub.legaleses] == NULL) {
3908 perror(
"Allocating new legalese string");
3912 strcpy(hd.legalese[hd.pub.legaleses++], c_name);
3913 if (db) *db = hd.pub;
3915 return (hd.pub.legaleses - 1);
3941 "libtcd error: attempt to access database when database not open\n");
3947 if (strlen(name) + 1 > hd.restriction_size) {
3948 LOG_ERROR(
"libtcd error: restriction exceeds size limit (%u).\n",
3949 hd.restriction_size);
3950 LOG_ERROR(
"The offending input is: %s\n", name);
3954 if (hd.pub.restriction_types == hd.max_restriction_types) {
3955 LOG_ERROR(
"You have exceeded the maximum number of restriction types!\n");
3956 LOG_ERROR(
"You cannot add any new restriction types.\n");
3958 "Modify the DEFAULT_RESTRICTION_BITS and rebuild the database.\n");
3962 c_name = clip_string(name);
3964 hd.restriction[hd.pub.restriction_types] =
3965 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3967 if (hd.restriction[hd.pub.restriction_types] == NULL) {
3968 perror(
"Allocating new restriction string");
3972 strcpy(hd.restriction[hd.pub.restriction_types++], c_name);
3973 if (db) *db = hd.pub;
3975 return (hd.pub.restriction_types - 1);
3981NV_INT32 find_or_add_restriction(
const NV_CHAR *name,
DB_HEADER_PUBLIC *db) {
3983 ret = find_restriction(name);
3984 if (ret < 0) ret = add_restriction(name, db);
3994 ret = find_tzfile(name);
3995 if (ret < 0) ret = add_tzfile(name, db);
4005 ret = find_country(name);
4006 if (ret < 0) ret = add_country(name, db);
4016 ret = find_datum(name);
4017 if (ret < 0) ret = add_datum(name, db);
4027 ret = find_legalese(name);
4028 if (ret < 0) ret = add_legalese(name, db);
4059 if (rec.max_time_add == rec.min_time_add &&
4060 rec.max_level_add == rec.min_level_add &&
4061 rec.max_level_multiply == rec.min_level_multiply &&
4062 rec.max_avg_level == 0 && rec.min_avg_level == 0 &&
4063 rec.max_direction == 361 && rec.min_direction == 361 &&
4064 rec.flood_begins == NULLSLACKOFFSET && rec.ebb_begins == NULLSLACKOFFSET)
4087static NV_U_INT32 header_checksum() {
4088 NV_U_INT32 checksum, i, save_pos;
4090 NV_U_INT32 crc_table[256] = {
4091 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
4092 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
4093 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
4094 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
4095 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
4096 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
4097 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
4098 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
4099 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
4100 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
4101 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
4102 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
4103 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
4104 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
4105 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
4106 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
4107 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
4108 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
4109 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
4110 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
4111 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
4112 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
4113 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
4114 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
4115 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
4116 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
4117 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
4118 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
4119 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
4120 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
4121 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
4122 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
4123 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
4124 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
4125 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
4126 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
4127 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
4128 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
4129 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
4130 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
4131 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
4132 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
4133 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D};
4137 "libtcd error: attempt to access database when database not open\n");
4141 save_pos = ftell(fp);
4143 fseek(fp, 0, SEEK_SET);
4145 if ((buf = (NV_U_BYTE *)calloc(hd.header_size,
sizeof(NV_U_BYTE))) == NULL) {
4146 perror(
"Allocating checksum buffer");
4152 assert(hd.header_size > 0);
4153 chk_fread(buf, hd.header_size, 1, fp);
4154 for (i = 0; i < (NV_U_INT32)hd.header_size; ++i) {
4155 checksum = crc_table[(checksum ^ buf[i]) & 0xff] ^ (checksum >> 8);
4161 fseek(fp, save_pos, SEEK_SET);
4182static NV_U_INT32 old_header_checksum() {
4183 NV_U_INT32 checksum, i, save_pos;
4188 "libtcd error: attempt to access database when database not open\n");
4192 save_pos = ftell(fp);
4196 fseek(fp, 0, SEEK_SET);
4198 if ((buf = (NV_U_BYTE *)calloc(hd.header_size,
sizeof(NV_U_BYTE))) == NULL) {
4199 perror(
"Allocating checksum buffer");
4203 chk_fread(buf, hd.header_size, 1, fp);
4205 for (i = 0; i < hd.header_size; ++i) checksum += buf[i];
4209 fseek(fp, save_pos, SEEK_SET);
4219static NV_CHAR *curtime() {
4220 static NV_CHAR buf[ONELINER_LENGTH];
4221 time_t t = time(NULL);
4222 require(strftime(buf, ONELINER_LENGTH,
"%Y-%m-%d %H:%M %Z", localtime(&t)) >
4231static NV_U_INT32 bits2bytes(NV_U_INT32 nbits) {
4232 if (nbits % 8)
return nbits / 8 + 1;
4252static void write_tide_db_header() {
4253 NV_U_INT32 i, size, pos;
4254 NV_INT32 start, temp_int;
4255 static NV_CHAR zero = 0;
4256 NV_U_BYTE *buf, checksum_c[4];
4260 "libtcd error: attempt to access database when database not open\n");
4265 fseek(fp, 0, SEEK_SET);
4267 fprintf(fp,
"[VERSION] = %s\n", LIBTCD_VERSION);
4268 fprintf(fp,
"[MAJOR REV] = %u\n", LIBTCD_MAJOR_REV);
4269 fprintf(fp,
"[MINOR REV] = %u\n", LIBTCD_MINOR_REV);
4271 fprintf(fp,
"[LAST MODIFIED] = %s\n", curtime());
4273 fprintf(fp,
"[HEADER SIZE] = %u\n", hd.header_size);
4274 fprintf(fp,
"[NUMBER OF RECORDS] = %u\n", hd.pub.number_of_records);
4276 fprintf(fp,
"[START YEAR] = %d\n", hd.pub.start_year);
4277 fprintf(fp,
"[NUMBER OF YEARS] = %u\n", hd.pub.number_of_years);
4279 fprintf(fp,
"[SPEED BITS] = %u\n", hd.speed_bits);
4280 fprintf(fp,
"[SPEED SCALE] = %u\n", hd.speed_scale);
4281 fprintf(fp,
"[SPEED OFFSET] = %d\n", hd.speed_offset);
4282 fprintf(fp,
"[EQUILIBRIUM BITS] = %u\n", hd.equilibrium_bits);
4283 fprintf(fp,
"[EQUILIBRIUM SCALE] = %u\n", hd.equilibrium_scale);
4284 fprintf(fp,
"[EQUILIBRIUM OFFSET] = %d\n", hd.equilibrium_offset);
4285 fprintf(fp,
"[NODE BITS] = %u\n", hd.node_bits);
4286 fprintf(fp,
"[NODE SCALE] = %u\n", hd.node_scale);
4287 fprintf(fp,
"[NODE OFFSET] = %d\n", hd.node_offset);
4288 fprintf(fp,
"[AMPLITUDE BITS] = %u\n", hd.amplitude_bits);
4289 fprintf(fp,
"[AMPLITUDE SCALE] = %u\n", hd.amplitude_scale);
4290 fprintf(fp,
"[EPOCH BITS] = %u\n", hd.epoch_bits);
4291 fprintf(fp,
"[EPOCH SCALE] = %u\n", hd.epoch_scale);
4293 fprintf(fp,
"[RECORD TYPE BITS] = %u\n", hd.record_type_bits);
4294 fprintf(fp,
"[LATITUDE BITS] = %u\n", hd.latitude_bits);
4295 fprintf(fp,
"[LATITUDE SCALE] = %u\n", hd.latitude_scale);
4296 fprintf(fp,
"[LONGITUDE BITS] = %u\n", hd.longitude_bits);
4297 fprintf(fp,
"[LONGITUDE SCALE] = %u\n", hd.longitude_scale);
4298 fprintf(fp,
"[RECORD SIZE BITS] = %u\n", hd.record_size_bits);
4300 fprintf(fp,
"[STATION BITS] = %u\n", hd.station_bits);
4302 fprintf(fp,
"[DATUM OFFSET BITS] = %u\n", hd.datum_offset_bits);
4303 fprintf(fp,
"[DATUM OFFSET SCALE] = %u\n", hd.datum_offset_scale);
4304 fprintf(fp,
"[DATE BITS] = %u\n", hd.date_bits);
4305 fprintf(fp,
"[MONTHS ON STATION BITS] = %u\n", hd.months_on_station_bits);
4306 fprintf(fp,
"[CONFIDENCE VALUE BITS] = %u\n", hd.confidence_value_bits);
4308 fprintf(fp,
"[TIME BITS] = %u\n", hd.time_bits);
4309 fprintf(fp,
"[LEVEL ADD BITS] = %u\n", hd.level_add_bits);
4310 fprintf(fp,
"[LEVEL ADD SCALE] = %u\n", hd.level_add_scale);
4311 fprintf(fp,
"[LEVEL MULTIPLY BITS] = %u\n", hd.level_multiply_bits);
4312 fprintf(fp,
"[LEVEL MULTIPLY SCALE] = %u\n", hd.level_multiply_scale);
4313 fprintf(fp,
"[DIRECTION BITS] = %u\n", hd.direction_bits);
4315 fprintf(fp,
"[LEVEL UNIT BITS] = %u\n", hd.level_unit_bits);
4316 fprintf(fp,
"[LEVEL UNIT TYPES] = %u\n", hd.pub.level_unit_types);
4317 fprintf(fp,
"[LEVEL UNIT SIZE] = %u\n", hd.level_unit_size);
4319 fprintf(fp,
"[DIRECTION UNIT BITS] = %u\n", hd.dir_unit_bits);
4320 fprintf(fp,
"[DIRECTION UNIT TYPES] = %u\n", hd.pub.dir_unit_types);
4321 fprintf(fp,
"[DIRECTION UNIT SIZE] = %u\n", hd.dir_unit_size);
4323 fprintf(fp,
"[RESTRICTION BITS] = %u\n", hd.restriction_bits);
4324 fprintf(fp,
"[RESTRICTION TYPES] = %u\n", hd.pub.restriction_types);
4325 fprintf(fp,
"[RESTRICTION SIZE] = %u\n", hd.restriction_size);
4327 fprintf(fp,
"[DATUM BITS] = %u\n", hd.datum_bits);
4328 fprintf(fp,
"[DATUM TYPES] = %u\n", hd.pub.datum_types);
4329 fprintf(fp,
"[DATUM SIZE] = %u\n", hd.datum_size);
4331 fprintf(fp,
"[LEGALESE BITS] = %u\n", hd.legalese_bits);
4332 fprintf(fp,
"[LEGALESE TYPES] = %u\n", hd.pub.legaleses);
4333 fprintf(fp,
"[LEGALESE SIZE] = %u\n", hd.legalese_size);
4335 fprintf(fp,
"[CONSTITUENT BITS] = %u\n", hd.constituent_bits);
4336 fprintf(fp,
"[CONSTITUENTS] = %u\n", hd.pub.constituents);
4337 fprintf(fp,
"[CONSTITUENT SIZE] = %u\n", hd.constituent_size);
4339 fprintf(fp,
"[TZFILE BITS] = %u\n", hd.tzfile_bits);
4340 fprintf(fp,
"[TZFILES] = %u\n", hd.pub.tzfiles);
4341 fprintf(fp,
"[TZFILE SIZE] = %u\n", hd.tzfile_size);
4343 fprintf(fp,
"[COUNTRY BITS] = %u\n", hd.country_bits);
4344 fprintf(fp,
"[COUNTRIES] = %u\n", hd.pub.countries);
4345 fprintf(fp,
"[COUNTRY SIZE] = %u\n", hd.country_size);
4347 fprintf(fp,
"[END OF FILE] = %u\n", hd.end_of_file);
4348 fprintf(fp,
"[END OF ASCII HEADER DATA]\n");
4354 for (i = start; i < hd.header_size; ++i) chk_fwrite(&zero, 1, 1, fp);
4359 bit_pack(checksum_c, 0, 32, header_checksum());
4360 chk_fwrite(checksum_c, 4, 1, fp);
4367 size = hd.pub.level_unit_types * hd.level_unit_size;
4369 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4370 perror(
"Allocating unit write buffer");
4373 memset(buf, 0, size);
4375 for (i = 0; i < hd.pub.level_unit_types; ++i) {
4376 assert(strlen(hd.level_unit[i]) + 1 <= hd.level_unit_size);
4377 strcpy((NV_CHAR *)&buf[pos], hd.level_unit[i]);
4378 pos += hd.level_unit_size;
4381 chk_fwrite(buf, pos, 1, fp);
4387 size = hd.pub.dir_unit_types * hd.dir_unit_size;
4389 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4390 perror(
"Allocating unit write buffer");
4393 memset(buf, 0, size);
4395 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
4396 assert(strlen(hd.dir_unit[i]) + 1 <= hd.dir_unit_size);
4397 strcpy((NV_CHAR *)&buf[pos], hd.dir_unit[i]);
4398 pos += hd.dir_unit_size;
4401 chk_fwrite(buf, pos, 1, fp);
4407 size = hd.max_restriction_types * hd.restriction_size;
4409 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4410 perror(
"Allocating restriction write buffer");
4413 memset(buf, 0, size);
4415 for (i = 0; i < hd.max_restriction_types; ++i) {
4416 if (i == hd.pub.restriction_types)
break;
4417 assert(strlen(hd.restriction[i]) + 1 <= hd.restriction_size);
4418 strcpy((NV_CHAR *)&buf[pos], hd.restriction[i]);
4419 pos += hd.restriction_size;
4421 memcpy(&buf[pos],
"__END__", 7);
4423 chk_fwrite(buf, size, 1, fp);
4429 size = hd.max_tzfiles * hd.tzfile_size;
4431 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4432 perror(
"Allocating tzfile write buffer");
4435 memset(buf, 0, size);
4437 for (i = 0; i < hd.max_tzfiles; ++i) {
4438 if (i == hd.pub.tzfiles)
break;
4439 assert(strlen(hd.tzfile[i]) + 1 <= hd.tzfile_size);
4440 strcpy((NV_CHAR *)&buf[pos], hd.tzfile[i]);
4441 pos += hd.tzfile_size;
4443 memcpy(&buf[pos],
"__END__", 7);
4445 chk_fwrite(buf, size, 1, fp);
4451 size = hd.max_countries * hd.country_size;
4453 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4454 perror(
"Allocating country write buffer");
4457 memset(buf, 0, size);
4459 for (i = 0; i < hd.max_countries; ++i) {
4460 if (i == hd.pub.countries)
break;
4461 assert(strlen(hd.country[i]) + 1 <= hd.country_size);
4462 strcpy((NV_CHAR *)&buf[pos], hd.country[i]);
4463 pos += hd.country_size;
4465 memcpy(&buf[pos],
"__END__", 7);
4467 chk_fwrite(buf, size, 1, fp);
4473 size = hd.max_datum_types * hd.datum_size;
4475 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4476 perror(
"Allocating datum write buffer");
4479 memset(buf, 0, size);
4481 for (i = 0; i < hd.max_datum_types; ++i) {
4482 if (i == hd.pub.datum_types)
break;
4483 assert(strlen(hd.datum[i]) + 1 <= hd.datum_size);
4484 strcpy((NV_CHAR *)&buf[pos], hd.datum[i]);
4485 pos += hd.datum_size;
4487 memcpy(&buf[pos],
"__END__", 7);
4489 chk_fwrite(buf, size, 1, fp);
4495 size = hd.max_legaleses * hd.legalese_size;
4497 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4498 perror(
"Allocating legalese write buffer");
4501 memset(buf, 0, size);
4503 for (i = 0; i < hd.max_legaleses; ++i) {
4504 if (i == hd.pub.legaleses)
break;
4505 assert(strlen(hd.legalese[i]) + 1 <= hd.legalese_size);
4506 strcpy((NV_CHAR *)&buf[pos], hd.legalese[i]);
4507 pos += hd.legalese_size;
4509 memcpy(&buf[pos],
"__END__", 7);
4511 chk_fwrite(buf, size, 1, fp);
4517 size = hd.pub.constituents * hd.constituent_size;
4519 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4520 perror(
"Allocating constituent write buffer");
4523 memset(buf, 0, size);
4525 for (i = 0; i < hd.pub.constituents; ++i) {
4526 assert(strlen(hd.constituent[i]) + 1 <= hd.constituent_size);
4527 strcpy((NV_CHAR *)&buf[pos], hd.constituent[i]);
4528 pos += hd.constituent_size;
4531 chk_fwrite(buf, pos, 1, fp);
4539 size = bits2bytes(hd.pub.constituents * hd.speed_bits);
4541 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4542 perror(
"Allocating speed write buffer");
4545 memset(buf, 0, size);
4547 for (i = 0; i < hd.pub.constituents; ++i) {
4548 temp_int = NINT(hd.speed[i] * hd.speed_scale) - hd.speed_offset;
4549 assert(temp_int >= 0);
4550 bit_pack(buf, pos, hd.speed_bits, temp_int);
4551 pos += hd.speed_bits;
4554 chk_fwrite(buf, size, 1, fp);
4560 size = bits2bytes(hd.pub.constituents * hd.pub.number_of_years *
4561 hd.equilibrium_bits);
4563 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4564 perror(
"Allocating equilibrium write buffer");
4567 memset(buf, 0, size);
4569 for (i = 0; i < hd.pub.constituents; ++i) {
4571 for (j = 0; j < hd.pub.number_of_years; ++j) {
4572 temp_int = NINT(hd.equilibrium[i][j] * hd.equilibrium_scale) -
4573 hd.equilibrium_offset;
4574 assert(temp_int >= 0);
4575 bit_pack(buf, pos, hd.equilibrium_bits, temp_int);
4576 pos += hd.equilibrium_bits;
4580 chk_fwrite(buf, size, 1, fp);
4587 bits2bytes(hd.pub.constituents * hd.pub.number_of_years * hd.node_bits);
4589 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4590 perror(
"Allocating node write buffer");
4593 memset(buf, 0, size);
4595 for (i = 0; i < hd.pub.constituents; ++i) {
4597 for (j = 0; j < hd.pub.number_of_years; ++j) {
4598 temp_int = NINT(hd.node_factor[i][j] * hd.node_scale) - hd.node_offset;
4599 assert(temp_int >= 0);
4600 bit_pack(buf, pos, hd.node_bits, temp_int);
4601 pos += hd.node_bits;
4605 chk_fwrite(buf, size, 1, fp);
4636static void unpack_string(NV_U_BYTE *buf, NV_U_INT32 bufsize, NV_U_INT32 *pos,
4637 NV_CHAR *outbuf, NV_U_INT32 outbuflen,
4638 const NV_CHAR *desc) {
4648 for (i = 0; c; ++i) {
4649 assert(*pos < bufsize);
4650 c = bit_unpack(buf, *pos, 8);
4652 if (i < outbuflen) {
4654 }
else if (i == outbuflen) {
4657 LOG_ERROR(
"libtcd warning: truncating overlong %s\n", desc);
4658 LOG_ERROR(
"The offending string starts with:\n%s\n", outbuf);
4686static void unpack_partial_tide_record(NV_U_BYTE *buf, NV_U_INT32 bufsize,
4696 rec->header.record_size = bit_unpack(buf, *pos, hd.record_size_bits);
4697 *pos += hd.record_size_bits;
4699 rec->header.record_type = bit_unpack(buf, *pos, hd.record_type_bits);
4700 *pos += hd.record_type_bits;
4702 temp_int = signed_bit_unpack(buf, *pos, hd.latitude_bits);
4703 rec->header.latitude = (NV_FLOAT64)temp_int / hd.latitude_scale;
4704 *pos += hd.latitude_bits;
4706 temp_int = signed_bit_unpack(buf, *pos, hd.longitude_bits);
4707 rec->header.longitude = (NV_FLOAT64)temp_int / hd.longitude_scale;
4708 *pos += hd.longitude_bits;
4713 rec->header.tzfile = bit_unpack(buf, *pos, hd.tzfile_bits);
4714 *pos += hd.tzfile_bits;
4716 unpack_string(buf, bufsize, pos, rec->header.name, ONELINER_LENGTH,
4719 rec->header.reference_station = signed_bit_unpack(buf, *pos, hd.station_bits);
4720 *pos += hd.station_bits;
4722 assert(*pos <= bufsize * 8);
4745static NV_INT32 read_partial_tide_record(NV_INT32 num,
TIDE_RECORD *rec) {
4747 NV_U_INT32 maximum_possible_size, pos;
4751 "libtcd error: attempt to access database when database not open\n");
4760 maximum_possible_size = hd.record_size_bits + hd.record_type_bits +
4761 hd.latitude_bits + hd.longitude_bits +
4762 hd.tzfile_bits + (ONELINER_LENGTH * 8) +
4764 maximum_possible_size = bits2bytes(maximum_possible_size);
4766 if ((buf = (NV_U_BYTE *)calloc(maximum_possible_size,
sizeof(NV_U_BYTE))) ==
4768 perror(
"Allocating partial tide record buffer");
4772 current_record = num;
4773 fseek(fp, tindex[num].address, SEEK_SET);
4778 size_t size = fread(buf, 1, maximum_possible_size, fp);
4779 unpack_partial_tide_record(buf, size, rec, &pos);
4799static NV_BOOL read_tide_db_header() {
4801 NV_CHAR varin[ONELINER_LENGTH], *info;
4802 NV_U_INT32 utemp, i, j, pos, size, key_count;
4803 NV_U_BYTE *buf, checksum_c[5];
4808 "libtcd error: attempt to access database when database not open\n");
4812 strcpy(hd.pub.version,
"NO VERSION");
4815 key_count =
sizeof(keys) /
sizeof(
KEY);
4818 memset(&hd, 0,
sizeof(hd));
4821 while (fgets(varin,
sizeof(varin), fp) != NULL) {
4822 if (strlen(varin) == ONELINER_LENGTH - 1) {
4823 if (varin[ONELINER_LENGTH - 2] !=
'\n') {
4824 LOG_ERROR(
"libtcd error: header line too long, begins with:\n");
4825 LOG_ERROR(
"%s\n", varin);
4826 LOG_ERROR(
"in file %s\n", filename);
4827 LOG_ERROR(
"Configured limit is %u\n", ONELINER_LENGTH - 1);
4833 if (strstr(varin,
"[END OF ASCII HEADER DATA]"))
break;
4836 info = strchr(varin,
'=');
4838 LOG_ERROR(
"libtcd error: invalid tide db header line:\n");
4839 LOG_ERROR(
"%s", varin);
4840 LOG_ERROR(
"in file %s\n", filename);
4847 for (i = 0; i < key_count; ++i) {
4848 if (strstr(varin, keys[i].keyphrase)) {
4849 if (!strcmp(keys[i].datatype,
"cstr"))
4850 strcpy((
char *)keys[i].address.cstr, clip_string(info));
4851 else if (!strcmp(keys[i].datatype,
"i32")) {
4852 if (sscanf(info,
"%d", keys[i].address.i32) != 1) {
4853 LOG_ERROR(
"libtcd error: invalid tide db header line:\n");
4854 LOG_ERROR(
"%s", varin);
4855 LOG_ERROR(
"in file %s\n", filename);
4859 }
else if (!strcmp(keys[i].datatype,
"ui32")) {
4860 if (sscanf(info,
"%u", keys[i].address.ui32) != 1) {
4861 LOG_ERROR(
"libtcd error: invalid tide db header line:\n");
4862 LOG_ERROR(
"%s", varin);
4863 LOG_ERROR(
"in file %s\n", filename);
4875 if (!strcmp(hd.pub.version,
"NO VERSION")) {
4876 LOG_ERROR(
"libtcd error: no version found in tide db header\n");
4877 LOG_ERROR(
"in file %s\n", filename);
4883 if (hd.pub.major_rev > LIBTCD_MAJOR_REV) {
4885 "libtcd error: major revision in TCD file (%u) exceeds major revision "
4888 LOG_ERROR(
"libtcd (%u). You must upgrade libtcd to read this file.\n",
4895 fseek(fp, hd.header_size, SEEK_SET);
4899 chk_fread(checksum_c, 4, 1, fp);
4900 utemp = bit_unpack(checksum_c, 0, 32);
4902 if (utemp != header_checksum()) {
4904 if (utemp != old_header_checksum()) {
4905 LOG_ERROR(
"libtcd error: header checksum error in file %s\n", filename);
4907 "Someone may have modified the ASCII portion of the header (don't do that),\n\
4908or it may just be corrupt.\n");
4913 LOG_ERROR(
"libtcd error: header checksum error in file %s\n", filename);
4915 "Someone may have modified the ASCII portion of the header (don't do that),\n\
4916or it may be an ancient pre-version-1.02 TCD file, or it may just be corrupt.\n\
4917Pre-version-1.02 TCD files can be read by building libtcd with COMPAT114\n\
4923 fseek(fp, hd.header_size + 4, SEEK_SET);
4928 hd.max_restriction_types = NINT(pow(2.0, (NV_FLOAT64)hd.restriction_bits));
4932 hd.max_tzfiles = NINT(pow(2.0, (NV_FLOAT64)hd.tzfile_bits));
4936 hd.max_countries = NINT(pow(2.0, (NV_FLOAT64)hd.country_bits));
4941 hd.max_datum_types = NINT(pow(2.0, (NV_FLOAT64)hd.datum_bits));
4946 if (hd.pub.major_rev < 2)
4947 hd.max_legaleses = 1;
4949 hd.max_legaleses = NINT(pow(2.0, (NV_FLOAT64)hd.legalese_bits));
4956 (NV_CHAR **)calloc(hd.pub.level_unit_types,
sizeof(NV_CHAR *));
4958 if ((buf = (NV_U_BYTE *)calloc(hd.level_unit_size,
sizeof(NV_U_BYTE))) ==
4960 perror(
"Allocating level unit read buffer");
4964 for (i = 0; i < hd.pub.level_unit_types; ++i) {
4965 chk_fread(buf, hd.level_unit_size, 1, fp);
4967 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
4968 strcpy(hd.level_unit[i], (NV_CHAR *)buf);
4974 hd.dir_unit = (NV_CHAR **)calloc(hd.pub.dir_unit_types,
sizeof(NV_CHAR *));
4976 if ((buf = (NV_U_BYTE *)calloc(hd.dir_unit_size,
sizeof(NV_U_BYTE))) ==
4978 perror(
"Allocating dir unit read buffer");
4982 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
4983 chk_fread(buf, hd.dir_unit_size, 1, fp);
4985 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
4986 strcpy(hd.dir_unit[i], (NV_CHAR *)buf);
4994 (NV_CHAR **)calloc(hd.max_restriction_types,
sizeof(NV_CHAR *));
4996 if ((buf = (NV_U_BYTE *)calloc(hd.restriction_size,
sizeof(NV_U_BYTE))) ==
4998 perror(
"Allocating restriction read buffer");
5002 hd.pub.restriction_types = 0;
5003 for (i = 0; i < hd.max_restriction_types; ++i) {
5004 chk_fread(buf, hd.restriction_size, 1, fp);
5005 if (!strcmp((
char *)buf,
"__END__")) {
5006 hd.pub.restriction_types = i;
5010 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5011 strcpy(hd.restriction[i], (NV_CHAR *)buf);
5014 fseek(fp, utemp + hd.max_restriction_types * hd.restriction_size, SEEK_SET);
5017 if (hd.pub.major_rev < 2)
5018 fseek(fp, hd.pedigree_size * NINT(pow(2.0, (NV_FLOAT64)hd.pedigree_bits)),
5020 hd.pub.pedigree_types = 1;
5025 hd.tzfile = (NV_CHAR **)calloc(hd.max_tzfiles,
sizeof(NV_CHAR *));
5027 if ((buf = (NV_U_BYTE *)calloc(hd.tzfile_size,
sizeof(NV_U_BYTE))) == NULL) {
5028 perror(
"Allocating tzfile read buffer");
5033 for (i = 0; i < hd.max_tzfiles; ++i) {
5034 chk_fread(buf, hd.tzfile_size, 1, fp);
5035 if (!strcmp((
char *)buf,
"__END__")) {
5039 hd.tzfile[i] = (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5040 strcpy(hd.tzfile[i], (NV_CHAR *)buf);
5043 fseek(fp, utemp + hd.max_tzfiles * hd.tzfile_size, SEEK_SET);
5048 hd.country = (NV_CHAR **)calloc(hd.max_countries,
sizeof(NV_CHAR *));
5050 if ((buf = (NV_U_BYTE *)calloc(hd.country_size,
sizeof(NV_U_BYTE))) == NULL) {
5051 perror(
"Allocating country read buffer");
5055 hd.pub.countries = 0;
5056 for (i = 0; i < hd.max_countries; ++i) {
5057 chk_fread(buf, hd.country_size, 1, fp);
5058 if (!strcmp((
char *)buf,
"__END__")) {
5059 hd.pub.countries = i;
5062 hd.country[i] = (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5063 strcpy(hd.country[i], (NV_CHAR *)buf);
5066 fseek(fp, utemp + hd.max_countries * hd.country_size, SEEK_SET);
5071 hd.datum = (NV_CHAR **)calloc(hd.max_datum_types,
sizeof(NV_CHAR *));
5073 if ((buf = (NV_U_BYTE *)calloc(hd.datum_size,
sizeof(NV_U_BYTE))) == NULL) {
5074 perror(
"Allocating datum read buffer");
5078 hd.pub.datum_types = 0;
5079 for (i = 0; i < hd.max_datum_types; ++i) {
5080 chk_fread(buf, hd.datum_size, 1, fp);
5081 if (!strcmp((
char *)buf,
"__END__")) {
5082 hd.pub.datum_types = i;
5085 hd.datum[i] = (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5086 strcpy(hd.datum[i], (NV_CHAR *)buf);
5089 fseek(fp, utemp + hd.max_datum_types * hd.datum_size, SEEK_SET);
5093 if (hd.pub.major_rev < 2) {
5094 hd.legalese = (NV_CHAR **)malloc(
sizeof(NV_CHAR *));
5095 assert(hd.legalese != NULL);
5096 hd.legalese[0] = (NV_CHAR *)malloc(5 *
sizeof(NV_CHAR));
5097 assert(hd.legalese[0] != NULL);
5098 strcpy(hd.legalese[0],
"NULL");
5099 hd.pub.legaleses = 1;
5102 hd.legalese = (NV_CHAR **)calloc(hd.max_legaleses,
sizeof(NV_CHAR *));
5104 if ((buf = (NV_U_BYTE *)calloc(hd.legalese_size,
sizeof(NV_U_BYTE))) ==
5106 perror(
"Allocating legalese read buffer");
5110 hd.pub.legaleses = 0;
5111 for (i = 0; i < hd.max_legaleses; ++i) {
5112 chk_fread(buf, hd.legalese_size, 1, fp);
5113 if (!strcmp((
char *)buf,
"__END__")) {
5114 hd.pub.legaleses = i;
5118 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5119 strcpy(hd.legalese[i], (NV_CHAR *)buf);
5122 fseek(fp, utemp + hd.max_legaleses * hd.legalese_size, SEEK_SET);
5127 hd.constituent = (NV_CHAR **)calloc(hd.pub.constituents,
sizeof(NV_CHAR *));
5129 if ((buf = (NV_U_BYTE *)calloc(hd.constituent_size,
sizeof(NV_U_BYTE))) ==
5131 perror(
"Allocating constituent read buffer");
5135 for (i = 0; i < hd.pub.constituents; ++i) {
5136 chk_fread(buf, hd.constituent_size, 1, fp);
5138 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5139 strcpy(hd.constituent[i], (NV_CHAR *)buf);
5143 if (hd.speed_offset < 0 || hd.equilibrium_offset < 0 || hd.node_offset < 0) {
5144 LOG_ERROR(
"libtcd WARNING: File: %s\n", filename);
5146 "WARNING: This TCD file was created by a pre-version-1.11 libtcd.\n\
5147Versions of libtcd prior to 1.11 contained a serious bug that can result\n\
5148in overflows in the speeds, equilibrium arguments, or node factors. This\n\
5149database should be rebuilt from the original data if possible.\n");
5156 hd.speed = (NV_FLOAT64 *)calloc(hd.pub.constituents,
sizeof(NV_FLOAT64));
5160 if (hd.pub.major_rev < 2)
5161 size = ((hd.pub.constituents * hd.speed_bits) / 8) + 1;
5163 size = bits2bytes(hd.pub.constituents * hd.speed_bits);
5165 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
5166 perror(
"Allocating speed read buffer");
5170 chk_fread(buf, size, 1, fp);
5172 for (i = 0; i < hd.pub.constituents; ++i) {
5173 temp_int = bit_unpack(buf, pos, hd.speed_bits);
5174 hd.speed[i] = (NV_FLOAT64)(temp_int + hd.speed_offset) / hd.speed_scale;
5175 pos += hd.speed_bits;
5176 assert(hd.speed[i] >= 0.0);
5183 (NV_FLOAT32 **)calloc(hd.pub.constituents,
sizeof(NV_FLOAT32 *));
5185 for (i = 0; i < hd.pub.constituents; ++i) {
5187 (NV_FLOAT32 *)calloc(hd.pub.number_of_years,
sizeof(NV_FLOAT32));
5192 if (hd.pub.major_rev < 2)
5194 ((hd.pub.constituents * hd.pub.number_of_years * hd.equilibrium_bits) /
5198 size = bits2bytes(hd.pub.constituents * hd.pub.number_of_years *
5199 hd.equilibrium_bits);
5201 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
5202 perror(
"Allocating equilibrium read buffer");
5206 chk_fread(buf, size, 1, fp);
5208 for (i = 0; i < hd.pub.constituents; ++i) {
5209 for (j = 0; j < hd.pub.number_of_years; ++j) {
5210 temp_int = bit_unpack(buf, pos, hd.equilibrium_bits);
5211 hd.equilibrium[i][j] =
5212 (NV_FLOAT32)(temp_int + hd.equilibrium_offset) / hd.equilibrium_scale;
5213 pos += hd.equilibrium_bits;
5221 (NV_FLOAT32 **)calloc(hd.pub.constituents,
sizeof(NV_FLOAT32 *));
5223 for (i = 0; i < hd.pub.constituents; ++i) {
5225 (NV_FLOAT32 *)calloc(hd.pub.number_of_years,
sizeof(NV_FLOAT32));
5230 if (hd.pub.major_rev < 2)
5232 ((hd.pub.constituents * hd.pub.number_of_years * hd.node_bits) / 8) + 1;
5235 bits2bytes(hd.pub.constituents * hd.pub.number_of_years * hd.node_bits);
5237 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
5238 perror(
"Allocating node read buffer");
5242 chk_fread(buf, size, 1, fp);
5244 for (i = 0; i < hd.pub.constituents; ++i) {
5245 for (j = 0; j < hd.pub.number_of_years; ++j) {
5246 temp_int = bit_unpack(buf, pos, hd.node_bits);
5247 hd.node_factor[i][j] =
5248 (NV_FLOAT32)(temp_int + hd.node_offset) / hd.node_scale;
5249 pos += hd.node_bits;
5250 assert(hd.node_factor[i][j] > 0.0);
5259 if (hd.pub.number_of_records) {
5260 if ((tindex = (
TIDE_INDEX *)calloc(hd.pub.number_of_records,
5262 perror(
"Allocating tide index");
5266 tindex[0].address = ftell(fp);
5270 for (i = 0; i < hd.pub.number_of_records; ++i) {
5274 if (i) tindex[i].address = tindex[i - 1].address + rec.header.record_size;
5276 read_partial_tide_record(i, &rec);
5280 tindex[i].record_size = rec.header.record_size;
5281 tindex[i].record_type = rec.header.record_type;
5282 tindex[i].reference_station = rec.header.reference_station;
5283 assert(rec.header.tzfile >= 0);
5284 tindex[i].tzfile = rec.header.tzfile;
5285 tindex[i].lat = NINT(rec.header.latitude * hd.latitude_scale);
5286 tindex[i].lon = NINT(rec.header.longitude * hd.longitude_scale);
5288 if ((tindex[i].name = (NV_CHAR *)calloc(strlen(rec.header.name) + 1,
5289 sizeof(NV_CHAR))) == NULL) {
5290 perror(
"Allocating index name memory");
5294 strcpy(tindex[i].name, rec.header.name);
5297 current_record = -1;
5320NV_BOOL open_tide_db(
const NV_CHAR *file) {
5322 current_record = -1;
5325 if (!strcmp(file, filename) && !modified)
5330 if ((fp = fopen(file,
"rb+")) == NULL) {
5331 if ((fp = fopen(file,
"rb")) == NULL)
return (NVFalse);
5333 boundscheck_monologue(file);
5334 strcpy(filename, file);
5335 return (read_tide_db_header());
5356void close_tide_db() {
5360 LOG_ERROR(
"libtcd warning: close_tide_db called when no database open\n");
5367 if (modified) write_tide_db_header();
5371 assert(hd.constituent);
5372 for (i = 0; i < hd.pub.constituents; ++i) {
5373 if (hd.constituent[i] != NULL) free(hd.constituent[i]);
5375 free(hd.constituent);
5376 hd.constituent = NULL;
5378 if (hd.speed != NULL) free(hd.speed);
5380 assert(hd.equilibrium);
5381 for (i = 0; i < hd.pub.constituents; ++i) {
5382 if (hd.equilibrium[i] != NULL) free(hd.equilibrium[i]);
5384 free(hd.equilibrium);
5385 hd.equilibrium = NULL;
5387 assert(hd.node_factor);
5388 for (i = 0; i < hd.pub.constituents; ++i) {
5389 if (hd.node_factor[i] != NULL) free(hd.node_factor[i]);
5391 free(hd.node_factor);
5392 hd.node_factor = NULL;
5394 assert(hd.level_unit);
5395 for (i = 0; i < hd.pub.level_unit_types; ++i) {
5396 if (hd.level_unit[i] != NULL) free(hd.level_unit[i]);
5398 free(hd.level_unit);
5399 hd.level_unit = NULL;
5401 assert(hd.dir_unit);
5402 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
5403 if (hd.dir_unit[i] != NULL) free(hd.dir_unit[i]);
5408 assert(hd.restriction);
5409 for (i = 0; i < hd.max_restriction_types; ++i) {
5410 if (hd.restriction[i] != NULL) free(hd.restriction[i]);
5412 free(hd.restriction);
5413 hd.restriction = NULL;
5415 assert(hd.legalese);
5416 for (i = 0; i < hd.max_legaleses; ++i) {
5417 if (hd.legalese[i] != NULL) free(hd.legalese[i]);
5423 for (i = 0; i < hd.max_tzfiles; ++i) {
5424 if (hd.tzfile[i] != NULL) free(hd.tzfile[i]);
5430 for (i = 0; i < hd.max_countries; ++i) {
5431 if (hd.country[i] != NULL) free(hd.country[i]);
5437 for (i = 0; i < hd.max_datum_types; ++i) {
5438 if (hd.datum[i] != NULL) free(hd.datum[i]);
5445 for (i = 0; i < hd.pub.number_of_records; ++i) {
5446 if (tindex[i].name) free(tindex[i].name);
5487NV_BOOL create_tide_db(
const NV_CHAR *file, NV_U_INT32 constituents,
5488 NV_CHAR
const *
const constituent[],
5489 const NV_FLOAT64 *speed, NV_INT32 start_year,
5490 NV_U_INT32 num_years,
5491 NV_FLOAT32
const *
const equilibrium[],
5492 NV_FLOAT32
const *
const node_factor[]) {
5494 NV_FLOAT64 min_value, max_value;
5499 assert(constituent);
5501 assert(equilibrium);
5502 assert(node_factor);
5503 for (i = 0; i < constituents; ++i) {
5504 if (speed[i] < 0.0) {
5506 "libtcd create_tide_db: somebody tried to set a negative speed "
5511 for (j = 0; j < num_years; ++j) {
5512 if (node_factor[i][j] <= 0.0) {
5514 "libtcd create_tide_db: somebody tried to set a negative or zero "
5515 "node factor (%f)\n",
5522 if (fp) close_tide_db();
5524 if ((fp = fopen(file,
"wb+")) == NULL) {
5531 memset(&hd, 0,
sizeof(hd));
5533 hd.pub.major_rev = LIBTCD_MAJOR_REV;
5534 hd.pub.minor_rev = LIBTCD_MINOR_REV;
5536 hd.header_size = DEFAULT_HEADER_SIZE;
5537 hd.pub.number_of_records = DEFAULT_NUMBER_OF_RECORDS;
5539 hd.pub.start_year = start_year;
5540 hd.pub.number_of_years = num_years;
5542 hd.pub.constituents = constituents;
5546 hd.constituent = (NV_CHAR **)calloc(hd.pub.constituents,
sizeof(NV_CHAR *));
5547 for (i = 0; i < hd.pub.constituents; ++i) {
5549 (NV_CHAR *)calloc(strlen(constituent[i]) + 1,
sizeof(NV_CHAR));
5550 strcpy(hd.constituent[i], constituent[i]);
5556 hd.constituent_bits = calculate_bits(hd.pub.constituents);
5560 hd.speed = (NV_FLOAT64 *)calloc(hd.pub.constituents,
sizeof(NV_FLOAT64));
5562 hd.speed_scale = DEFAULT_SPEED_SCALE;
5563 min_value = 99999999.0;
5564 max_value = -99999999.0;
5565 for (i = 0; i < hd.pub.constituents; ++i) {
5566 if (speed[i] < min_value) min_value = speed[i];
5567 if (speed[i] > max_value) max_value = speed[i];
5569 hd.speed[i] = speed[i];
5575 hd.speed_offset = (NINT(min_value * hd.speed_scale));
5576 temp_int = NINT(max_value * hd.speed_scale) - hd.speed_offset;
5577 assert(temp_int >= 0);
5578 hd.speed_bits = calculate_bits((NV_U_INT32)temp_int);
5580 assert(hd.speed_bits < 32);
5585 (NV_FLOAT32 **)calloc(hd.pub.constituents,
sizeof(NV_FLOAT32 *));
5587 hd.equilibrium_scale = DEFAULT_EQUILIBRIUM_SCALE;
5588 min_value = 99999999.0;
5589 max_value = -99999999.0;
5590 for (i = 0; i < hd.pub.constituents; ++i) {
5592 (NV_FLOAT32 *)calloc(hd.pub.number_of_years,
sizeof(NV_FLOAT32));
5593 for (j = 0; j < hd.pub.number_of_years; ++j) {
5594 if (equilibrium[i][j] < min_value) min_value = equilibrium[i][j];
5595 if (equilibrium[i][j] > max_value) max_value = equilibrium[i][j];
5597 hd.equilibrium[i][j] = equilibrium[i][j];
5604 hd.equilibrium_offset = (NINT(min_value * hd.equilibrium_scale));
5605 temp_int = NINT(max_value * hd.equilibrium_scale) - hd.equilibrium_offset;
5606 assert(temp_int >= 0);
5607 hd.equilibrium_bits = calculate_bits((NV_U_INT32)temp_int);
5612 (NV_FLOAT32 **)calloc(hd.pub.constituents,
sizeof(NV_FLOAT32 *));
5614 hd.node_scale = DEFAULT_NODE_SCALE;
5615 min_value = 99999999.0;
5616 max_value = -99999999.0;
5617 for (i = 0; i < hd.pub.constituents; ++i) {
5619 (NV_FLOAT32 *)calloc(hd.pub.number_of_years,
sizeof(NV_FLOAT32));
5620 for (j = 0; j < hd.pub.number_of_years; ++j) {
5621 if (node_factor[i][j] < min_value) min_value = node_factor[i][j];
5622 if (node_factor[i][j] > max_value) max_value = node_factor[i][j];
5624 hd.node_factor[i][j] = node_factor[i][j];
5631 hd.node_offset = (NINT(min_value * hd.node_scale));
5632 temp_int = NINT(max_value * hd.node_scale) - hd.node_offset;
5633 assert(temp_int >= 0);
5634 hd.node_bits = calculate_bits((NV_U_INT32)temp_int);
5638 hd.amplitude_bits = DEFAULT_AMPLITUDE_BITS;
5639 hd.amplitude_scale = DEFAULT_AMPLITUDE_SCALE;
5640 hd.epoch_bits = DEFAULT_EPOCH_BITS;
5641 hd.epoch_scale = DEFAULT_EPOCH_SCALE;
5643 hd.record_type_bits = DEFAULT_RECORD_TYPE_BITS;
5644 hd.latitude_bits = DEFAULT_LATITUDE_BITS;
5645 hd.latitude_scale = DEFAULT_LATITUDE_SCALE;
5646 hd.longitude_bits = DEFAULT_LONGITUDE_BITS;
5647 hd.longitude_scale = DEFAULT_LONGITUDE_SCALE;
5648 hd.record_size_bits = DEFAULT_RECORD_SIZE_BITS;
5650 hd.station_bits = DEFAULT_STATION_BITS;
5652 hd.datum_offset_bits = DEFAULT_DATUM_OFFSET_BITS;
5653 hd.datum_offset_scale = DEFAULT_DATUM_OFFSET_SCALE;
5654 hd.date_bits = DEFAULT_DATE_BITS;
5655 hd.months_on_station_bits = DEFAULT_MONTHS_ON_STATION_BITS;
5656 hd.confidence_value_bits = DEFAULT_CONFIDENCE_VALUE_BITS;
5658 hd.time_bits = DEFAULT_TIME_BITS;
5659 hd.level_add_bits = DEFAULT_LEVEL_ADD_BITS;
5660 hd.level_add_scale = DEFAULT_LEVEL_ADD_SCALE;
5661 hd.level_multiply_bits = DEFAULT_LEVEL_MULTIPLY_BITS;
5662 hd.level_multiply_scale = DEFAULT_LEVEL_MULTIPLY_SCALE;
5663 hd.direction_bits = DEFAULT_DIRECTION_BITS;
5665 hd.constituent_size = DEFAULT_CONSTITUENT_SIZE;
5666 hd.level_unit_size = DEFAULT_LEVEL_UNIT_SIZE;
5667 hd.dir_unit_size = DEFAULT_DIR_UNIT_SIZE;
5668 hd.restriction_size = DEFAULT_RESTRICTION_SIZE;
5669 hd.tzfile_size = DEFAULT_TZFILE_SIZE;
5670 hd.country_size = DEFAULT_COUNTRY_SIZE;
5671 hd.datum_size = DEFAULT_DATUM_SIZE;
5672 hd.legalese_size = DEFAULT_LEGALESE_SIZE;
5676 hd.pub.level_unit_types = DEFAULT_LEVEL_UNIT_TYPES;
5677 hd.level_unit_bits = calculate_bits(hd.pub.level_unit_types - 1);
5680 (NV_CHAR **)calloc(hd.pub.level_unit_types,
sizeof(NV_CHAR *));
5681 for (i = 0; i < hd.pub.level_unit_types; ++i) {
5683 (NV_CHAR *)calloc(strlen(level_unit[i]) + 1,
sizeof(NV_CHAR));
5684 strcpy(hd.level_unit[i], level_unit[i]);
5689 hd.pub.dir_unit_types = DEFAULT_DIR_UNIT_TYPES;
5690 hd.dir_unit_bits = calculate_bits(hd.pub.dir_unit_types - 1);
5692 hd.dir_unit = (NV_CHAR **)calloc(hd.pub.dir_unit_types,
sizeof(NV_CHAR *));
5693 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
5695 (NV_CHAR *)calloc(strlen(dir_unit[i]) + 1,
sizeof(NV_CHAR));
5696 strcpy(hd.dir_unit[i], dir_unit[i]);
5701 hd.restriction_bits = DEFAULT_RESTRICTION_BITS;
5702 hd.max_restriction_types = NINT(pow(2.0, (NV_FLOAT64)hd.restriction_bits));
5703 hd.pub.restriction_types = DEFAULT_RESTRICTION_TYPES;
5706 (NV_CHAR **)calloc(hd.max_restriction_types,
sizeof(NV_CHAR *));
5707 for (i = 0; i < hd.max_restriction_types; ++i) {
5708 if (i == hd.pub.restriction_types)
break;
5711 (NV_CHAR *)calloc(strlen(restriction[i]) + 1,
sizeof(NV_CHAR));
5712 strcpy(hd.restriction[i], restriction[i]);
5717 hd.legalese_bits = DEFAULT_LEGALESE_BITS;
5718 hd.max_legaleses = NINT(pow(2.0, (NV_FLOAT64)hd.legalese_bits));
5719 hd.pub.legaleses = DEFAULT_LEGALESES;
5721 hd.legalese = (NV_CHAR **)calloc(hd.max_legaleses,
sizeof(NV_CHAR *));
5722 for (i = 0; i < hd.max_legaleses; ++i) {
5723 if (i == hd.pub.legaleses)
break;
5726 (NV_CHAR *)calloc(strlen(legalese[i]) + 1,
sizeof(NV_CHAR));
5727 strcpy(hd.legalese[i], legalese[i]);
5732 hd.tzfile_bits = DEFAULT_TZFILE_BITS;
5733 hd.max_tzfiles = NINT(pow(2.0, (NV_FLOAT64)hd.tzfile_bits));
5734 hd.pub.tzfiles = DEFAULT_TZFILES;
5736 hd.tzfile = (NV_CHAR **)calloc(hd.max_tzfiles,
sizeof(NV_CHAR *));
5737 for (i = 0; i < hd.max_tzfiles; ++i) {
5738 if (i == hd.pub.tzfiles)
break;
5740 hd.tzfile[i] = (NV_CHAR *)calloc(strlen(tzfile[i]) + 1,
sizeof(NV_CHAR));
5741 strcpy(hd.tzfile[i], tzfile[i]);
5746 hd.country_bits = DEFAULT_COUNTRY_BITS;
5747 hd.max_countries = NINT(pow(2.0, (NV_FLOAT64)hd.country_bits));
5748 hd.pub.countries = DEFAULT_COUNTRIES;
5750 hd.country = (NV_CHAR **)calloc(hd.max_countries,
sizeof(NV_CHAR *));
5751 for (i = 0; i < hd.max_countries; ++i) {
5752 if (i == hd.pub.countries)
break;
5754 hd.country[i] = (NV_CHAR *)calloc(strlen(country[i]) + 1,
sizeof(NV_CHAR));
5755 strcpy(hd.country[i], country[i]);
5760 hd.datum_bits = DEFAULT_DATUM_BITS;
5761 hd.max_datum_types = NINT(pow(2.0, (NV_FLOAT64)hd.datum_bits));
5762 hd.pub.datum_types = DEFAULT_DATUM_TYPES;
5764 hd.datum = (NV_CHAR **)calloc(hd.max_datum_types,
sizeof(NV_CHAR *));
5765 for (i = 0; i < hd.max_datum_types; ++i) {
5766 if (i == hd.pub.datum_types)
break;
5768 hd.datum[i] = (NV_CHAR *)calloc(strlen(datum[i]) + 1,
sizeof(NV_CHAR));
5769 strcpy(hd.datum[i], datum[i]);
5779 i = (open_tide_db(file));
5783 hd.end_of_file = ftell(fp);
5787 write_tide_db_header();
5796static NV_BOOL check_date(NV_U_INT32 date) {
5802 if (m < 1 || m > 12 || d < 1 || d > 31)
return NVFalse;
5816static NV_BOOL check_tide_record(
TIDE_RECORD *rec) {
5818 NV_BOOL ret = NVTrue;
5821 LOG_ERROR(
"libtcd error: null pointer passed to check_tide_record\n");
5827 boundscheck_oneliner(rec->header.name);
5828 boundscheck_oneliner(rec->source);
5829 boundscheck_monologue(rec->comments);
5830 boundscheck_monologue(rec->notes);
5831 boundscheck_oneliner(rec->station_id_context);
5832 boundscheck_oneliner(rec->station_id);
5833 boundscheck_monologue(rec->xfields);
5836 if (rec->header.record_type == REFERENCE_STATION && rec->units > 0)
5837 rec->level_units = rec->units;
5840 if (rec->header.latitude < -90.0 || rec->header.latitude > 90.0 ||
5841 rec->header.longitude < -180.0 || rec->header.longitude > 180.0) {
5842 LOG_ERROR(
"libtcd error: bad coordinates in tide record\n");
5846 if (rec->header.tzfile < 0 ||
5847 rec->header.tzfile >= (NV_INT32)hd.pub.tzfiles) {
5848 LOG_ERROR(
"libtcd error: bad tzfile in tide record\n");
5852 if (rec->header.name[0] ==
'\0') {
5853 LOG_ERROR(
"libtcd error: null name in tide record\n");
5857 if (rec->country < 0 || rec->country >= (NV_INT32)hd.pub.countries) {
5858 LOG_ERROR(
"libtcd error: bad country in tide record\n");
5862 if (rec->restriction >= hd.pub.restriction_types) {
5863 LOG_ERROR(
"libtcd error: bad restriction in tide record\n");
5867 if (rec->legalese >= hd.pub.legaleses) {
5868 LOG_ERROR(
"libtcd error: bad legalese in tide record\n");
5872 if (!check_date(rec->date_imported)) {
5873 LOG_ERROR(
"libtcd error: bad date_imported in tide record\n");
5877 if (rec->direction_units >= hd.pub.dir_unit_types) {
5878 LOG_ERROR(
"libtcd error: bad direction_units in tide record\n");
5882 if (rec->min_direction < 0 || rec->min_direction > 361) {
5883 LOG_ERROR(
"libtcd error: min_direction out of range in tide record\n");
5887 if (rec->max_direction < 0 || rec->max_direction > 361) {
5888 LOG_ERROR(
"libtcd error: max_direction out of range in tide record\n");
5892 if (rec->level_units >= hd.pub.level_unit_types) {
5893 LOG_ERROR(
"libtcd error: bad units in tide record\n");
5897 switch (rec->header.record_type) {
5898 case REFERENCE_STATION:
5899 if (rec->header.reference_station != -1) {
5900 LOG_ERROR(
"libtcd error: type 1 record, reference_station != -1\n");
5904 if (rec->datum_offset < -13421.7728 || rec->datum_offset > 13421.7727) {
5905 LOG_ERROR(
"libtcd error: datum_offset out of range in tide record\n");
5909 if (rec->datum < 0 || rec->datum >= (NV_INT32)hd.pub.datum_types) {
5910 LOG_ERROR(
"libtcd error: bad datum in tide record\n");
5914 if (rec->zone_offset < -4096 || rec->zone_offset > 4095 ||
5915 rec->zone_offset % 100 >= 60) {
5916 LOG_ERROR(
"libtcd error: bad zone_offset in tide record\n");
5920 if (!check_date(rec->expiration_date)) {
5921 LOG_ERROR(
"libtcd error: bad expiration_date in tide record\n");
5925 if (rec->months_on_station > 1023) {
5927 "libtcd error: months_on_station out of range in tide record\n");
5931 if (!check_date(rec->last_date_on_station)) {
5932 LOG_ERROR(
"libtcd error: bad last_date_on_station in tide record\n");
5936 if (rec->confidence > 15) {
5937 LOG_ERROR(
"libtcd error: confidence out of range in tide record\n");
5942 for (i = 0; i < hd.pub.constituents; ++i) {
5943 if (rec->amplitude[i] < 0.0 || rec->amplitude[i] > 52.4287) {
5945 "libtcd error: constituent amplitude out of range in tide "
5951 for (i = 0; i < hd.pub.constituents; ++i) {
5952 if (rec->epoch[i] < 0.0 || rec->epoch[i] > 360.0) {
5954 "libtcd error: constituent epoch out of range in tide record\n");
5962 case SUBORDINATE_STATION:
5963 if (rec->header.reference_station < 0 ||
5964 rec->header.reference_station >= (NV_INT32)hd.pub.number_of_records) {
5965 LOG_ERROR(
"libtcd error: bad reference_station in tide record\n");
5969 if (rec->min_time_add < -4096 || rec->min_time_add > 4095 ||
5970 rec->min_time_add % 100 >= 60) {
5971 LOG_ERROR(
"libtcd error: bad min_time_add in tide record\n");
5975 if (rec->min_level_add < -65.536 || rec->min_level_add > 65.535) {
5976 LOG_ERROR(
"libtcd error: min_level_add out of range in tide record\n");
5980 if (rec->min_level_multiply < 0.0 || rec->min_level_multiply > 65.535) {
5982 "libtcd error: min_level_multiply out of range in tide record\n");
5986 if (rec->max_time_add < -4096 || rec->max_time_add > 4095 ||
5987 rec->max_time_add % 100 >= 60) {
5988 LOG_ERROR(
"libtcd error: bad max_time_add in tide record\n");
5992 if (rec->max_level_add < -65.536 || rec->max_level_add > 65.535) {
5993 LOG_ERROR(
"libtcd error: max_level_add out of range in tide record\n");
5997 if (rec->max_level_multiply < 0.0 || rec->max_level_multiply > 65.535) {
5999 "libtcd error: max_level_multiply out of range in tide record\n");
6003 if (rec->flood_begins != NULLSLACKOFFSET &&
6004 (rec->flood_begins < -4096 || rec->flood_begins > 4095 ||
6005 rec->flood_begins % 100 >= 60)) {
6006 LOG_ERROR(
"libtcd error: bad flood_begins in tide record\n");
6010 if (rec->ebb_begins != NULLSLACKOFFSET &&
6011 (rec->ebb_begins < -4096 || rec->ebb_begins > 4095 ||
6012 rec->ebb_begins % 100 >= 60)) {
6013 LOG_ERROR(
"libtcd error: bad ebb_begins in tide record\n");
6020 LOG_ERROR(
"libtcd error: invalid record_type in tide record\n");
6024 if (ret == NVFalse) dump_tide_record(rec);
6035 NV_U_INT32 i, count = 0, name_size, source_size, comments_size, notes_size,
6036 station_id_context_size, station_id_size, xfields_size;
6042 name_size = strlen(clip_string(rec->header.name)) + 1;
6043 source_size = strlen(clip_string(rec->source)) + 1;
6044 comments_size = strlen(clip_string(rec->comments)) + 1;
6045 notes_size = strlen(clip_string(rec->notes)) + 1;
6046 station_id_context_size = strlen(clip_string(rec->station_id_context)) + 1;
6047 station_id_size = strlen(clip_string(rec->station_id)) + 1;
6049 xfields_size = strlen(rec->xfields) + 1;
6051 rec->header.record_size =
6052 hd.record_size_bits + hd.record_type_bits + hd.latitude_bits +
6053 hd.longitude_bits + hd.station_bits + hd.tzfile_bits + (name_size * 8) +
6055 hd.country_bits + (source_size * 8) + hd.restriction_bits +
6056 (comments_size * 8) + (notes_size * 8) + hd.legalese_bits +
6057 (station_id_context_size * 8) + (station_id_size * 8) + hd.date_bits +
6058 (xfields_size * 8) + hd.dir_unit_bits + hd.direction_bits +
6059 hd.direction_bits + hd.level_unit_bits;
6061 switch (rec->header.record_type) {
6062 case REFERENCE_STATION:
6063 rec->header.record_size += hd.datum_offset_bits + hd.datum_bits +
6064 hd.time_bits + hd.date_bits +
6065 hd.months_on_station_bits + hd.date_bits +
6066 hd.confidence_value_bits + hd.constituent_bits;
6068 for (i = 0; i < hd.pub.constituents; ++i) {
6069 assert(rec->amplitude[i] >= 0.0);
6070 if (rec->amplitude[i] >= AMPLITUDE_EPSILON) ++count;
6073 rec->header.record_size +=
6074 (count * hd.constituent_bits + count * hd.amplitude_bits +
6075 count * hd.epoch_bits);
6079 case SUBORDINATE_STATION:
6080 rec->header.record_size += hd.time_bits + hd.level_add_bits +
6081 hd.level_multiply_bits + hd.time_bits +
6082 hd.level_add_bits + hd.level_multiply_bits +
6083 hd.time_bits + hd.time_bits;
6090 rec->header.record_size = bits2bytes(rec->header.record_size);
6097static void pack_string(NV_U_BYTE *buf, NV_U_INT32 *pos, NV_CHAR *s) {
6098 NV_U_INT32 i, temp_size;
6102 temp_size = strlen(s) + 1;
6103 for (i = 0; i < temp_size; ++i) {
6104 bit_pack(buf, *pos, 8, s[i]);
6129static void pack_tide_record(
TIDE_RECORD *rec, NV_U_BYTE **bufptr,
6130 NV_U_INT32 *bufsize) {
6131 NV_U_INT32 i, pos, constituent_count;
6140 boundscheck_oneliner(rec->header.name);
6141 boundscheck_oneliner(rec->source);
6142 boundscheck_monologue(rec->comments);
6143 boundscheck_monologue(rec->notes);
6144 boundscheck_oneliner(rec->station_id_context);
6145 boundscheck_oneliner(rec->station_id);
6146 boundscheck_monologue(rec->xfields);
6148 constituent_count = figure_size(rec);
6151 (NV_U_BYTE *)calloc(rec->header.record_size,
sizeof(NV_U_BYTE)))) {
6152 perror(
"libtcd can't allocate memory in pack_tide_record");
6162 bit_pack(buf, pos, hd.record_size_bits, rec->header.record_size);
6163 pos += hd.record_size_bits;
6165 bit_pack(buf, pos, hd.record_type_bits, rec->header.record_type);
6166 pos += hd.record_type_bits;
6168 temp_int = NINT(rec->header.latitude * hd.latitude_scale);
6169 bit_pack(buf, pos, hd.latitude_bits, temp_int);
6170 pos += hd.latitude_bits;
6172 temp_int = NINT(rec->header.longitude * hd.longitude_scale);
6173 bit_pack(buf, pos, hd.longitude_bits, temp_int);
6174 pos += hd.longitude_bits;
6180 bit_pack(buf, pos, hd.tzfile_bits, rec->header.tzfile);
6181 pos += hd.tzfile_bits;
6183 pack_string(buf, &pos, clip_string(rec->header.name));
6185 bit_pack(buf, pos, hd.station_bits, rec->header.reference_station);
6186 pos += hd.station_bits;
6188 bit_pack(buf, pos, hd.country_bits, rec->country);
6189 pos += hd.country_bits;
6191 pack_string(buf, &pos, clip_string(rec->source));
6193 bit_pack(buf, pos, hd.restriction_bits, rec->restriction);
6194 pos += hd.restriction_bits;
6196 pack_string(buf, &pos, clip_string(rec->comments));
6197 pack_string(buf, &pos, clip_string(rec->notes));
6199 bit_pack(buf, pos, hd.legalese_bits, rec->legalese);
6200 pos += hd.legalese_bits;
6202 pack_string(buf, &pos, clip_string(rec->station_id_context));
6203 pack_string(buf, &pos, clip_string(rec->station_id));
6205 bit_pack(buf, pos, hd.date_bits, rec->date_imported);
6206 pos += hd.date_bits;
6209 pack_string(buf, &pos, rec->xfields);
6211 bit_pack(buf, pos, hd.dir_unit_bits, rec->direction_units);
6212 pos += hd.dir_unit_bits;
6214 bit_pack(buf, pos, hd.direction_bits, rec->min_direction);
6215 pos += hd.direction_bits;
6217 bit_pack(buf, pos, hd.direction_bits, rec->max_direction);
6218 pos += hd.direction_bits;
6221 bit_pack(buf, pos, hd.level_unit_bits, rec->level_units);
6222 pos += hd.level_unit_bits;
6226 if (rec->header.record_type == REFERENCE_STATION) {
6227 temp_int = NINT(rec->datum_offset * hd.datum_offset_scale);
6228 bit_pack(buf, pos, hd.datum_offset_bits, temp_int);
6229 pos += hd.datum_offset_bits;
6231 bit_pack(buf, pos, hd.datum_bits, rec->datum);
6232 pos += hd.datum_bits;
6234 bit_pack(buf, pos, hd.time_bits, rec->zone_offset);
6235 pos += hd.time_bits;
6237 bit_pack(buf, pos, hd.date_bits, rec->expiration_date);
6238 pos += hd.date_bits;
6240 bit_pack(buf, pos, hd.months_on_station_bits, rec->months_on_station);
6241 pos += hd.months_on_station_bits;
6243 bit_pack(buf, pos, hd.date_bits, rec->last_date_on_station);
6244 pos += hd.date_bits;
6246 bit_pack(buf, pos, hd.confidence_value_bits, rec->confidence);
6247 pos += hd.confidence_value_bits;
6249 bit_pack(buf, pos, hd.constituent_bits, constituent_count);
6250 pos += hd.constituent_bits;
6252 for (i = 0; i < hd.pub.constituents; ++i) {
6253 if (rec->amplitude[i] >= AMPLITUDE_EPSILON) {
6254 bit_pack(buf, pos, hd.constituent_bits, i);
6255 pos += hd.constituent_bits;
6257 temp_int = NINT(rec->amplitude[i] * hd.amplitude_scale);
6259 bit_pack(buf, pos, hd.amplitude_bits, temp_int);
6260 pos += hd.amplitude_bits;
6262 temp_int = NINT(rec->epoch[i] * hd.epoch_scale);
6263 bit_pack(buf, pos, hd.epoch_bits, temp_int);
6264 pos += hd.epoch_bits;
6270 else if (rec->header.record_type == SUBORDINATE_STATION) {
6271 bit_pack(buf, pos, hd.time_bits, rec->min_time_add);
6272 pos += hd.time_bits;
6274 temp_int = NINT(rec->min_level_add * hd.level_add_scale);
6275 bit_pack(buf, pos, hd.level_add_bits, temp_int);
6276 pos += hd.level_add_bits;
6278 temp_int = NINT(rec->min_level_multiply * hd.level_multiply_scale);
6279 bit_pack(buf, pos, hd.level_multiply_bits, temp_int);
6280 pos += hd.level_multiply_bits;
6282 bit_pack(buf, pos, hd.time_bits, rec->max_time_add);
6283 pos += hd.time_bits;
6285 temp_int = NINT(rec->max_level_add * hd.level_add_scale);
6286 bit_pack(buf, pos, hd.level_add_bits, temp_int);
6287 pos += hd.level_add_bits;
6289 temp_int = NINT(rec->max_level_multiply * hd.level_multiply_scale);
6290 bit_pack(buf, pos, hd.level_multiply_bits, temp_int);
6291 pos += hd.level_multiply_bits;
6293 bit_pack(buf, pos, hd.time_bits, rec->flood_begins);
6294 pos += hd.time_bits;
6296 bit_pack(buf, pos, hd.time_bits, rec->ebb_begins);
6297 pos += hd.time_bits;
6301 LOG_ERROR(
"libtcd error: Record type %d is undefined\n",
6302 rec->header.record_type);
6306 *bufsize = rec->header.record_size;
6307 assert(*bufsize == bits2bytes(pos));
6332static NV_BOOL write_tide_record(NV_INT32 num,
TIDE_RECORD *rec) {
6333 NV_U_BYTE *buf = NULL;
6334 NV_U_INT32 bufsize = 0;
6338 "libtcd error: attempt to access database when database not open\n");
6343 pack_tide_record(rec, &buf, &bufsize);
6348 fseek(fp, tindex[num].address, SEEK_SET);
6352 chk_fwrite(buf, bufsize, 1, fp);
6377 return (read_tide_record(current_record + 1, rec));
6401static void unpack_tide_record(NV_U_BYTE *buf, NV_U_INT32 bufsize,
6404 NV_U_INT32 i, j, pos, count;
6411 int r = find_dir_units(
"degrees true");
6413 rec->direction_units = (NV_U_BYTE)r;
6415 rec->min_direction = rec->max_direction = 361;
6416 rec->flood_begins = rec->ebb_begins = NULLSLACKOFFSET;
6417 rec->header.record_number = current_record;
6419 unpack_partial_tide_record(buf, bufsize, rec, &pos);
6421 switch (rec->header.record_type) {
6422 case REFERENCE_STATION:
6423 case SUBORDINATE_STATION:
6426 LOG_ERROR(
"libtcd fatal error: tried to read type %d tide record.\n",
6427 rec->header.record_type);
6429 "This version of libtcd only supports types 1 and 2. Perhaps you "
6430 "should\nupgrade.\n");
6434 switch (hd.pub.major_rev) {
6441 rec->country = bit_unpack(buf, pos, hd.country_bits);
6442 pos += hd.country_bits;
6445 pos += hd.pedigree_bits;
6447 unpack_string(buf, bufsize, &pos, rec->source, ONELINER_LENGTH,
6450 rec->restriction = bit_unpack(buf, pos, hd.restriction_bits);
6451 pos += hd.restriction_bits;
6453 unpack_string(buf, bufsize, &pos, rec->comments, MONOLOGUE_LENGTH,
6456 if (rec->header.record_type == REFERENCE_STATION) {
6457 rec->level_units = bit_unpack(buf, pos, hd.level_unit_bits);
6459 rec->units = rec->level_units;
6461 pos += hd.level_unit_bits;
6463 temp_int = signed_bit_unpack(buf, pos, hd.datum_offset_bits);
6464 rec->datum_offset = (NV_FLOAT32)temp_int / hd.datum_offset_scale;
6465 pos += hd.datum_offset_bits;
6467 rec->datum = bit_unpack(buf, pos, hd.datum_bits);
6468 pos += hd.datum_bits;
6470 rec->zone_offset = signed_bit_unpack(buf, pos, hd.time_bits);
6471 pos += hd.time_bits;
6473 rec->expiration_date = bit_unpack(buf, pos, hd.date_bits);
6474 pos += hd.date_bits;
6476 rec->months_on_station =
6477 bit_unpack(buf, pos, hd.months_on_station_bits);
6478 pos += hd.months_on_station_bits;
6480 rec->last_date_on_station = bit_unpack(buf, pos, hd.date_bits);
6481 pos += hd.date_bits;
6483 rec->confidence = bit_unpack(buf, pos, hd.confidence_value_bits);
6484 pos += hd.confidence_value_bits;
6486 for (i = 0; i < hd.pub.constituents; ++i) {
6487 rec->amplitude[i] = 0.0;
6488 rec->epoch[i] = 0.0;
6491 count = bit_unpack(buf, pos, hd.constituent_bits);
6492 pos += hd.constituent_bits;
6494 for (i = 0; i < count; ++i) {
6495 j = bit_unpack(buf, pos, hd.constituent_bits);
6496 pos += hd.constituent_bits;
6499 (NV_FLOAT32)bit_unpack(buf, pos, hd.amplitude_bits) /
6501 pos += hd.amplitude_bits;
6504 (NV_FLOAT32)bit_unpack(buf, pos, hd.epoch_bits) / hd.epoch_scale;
6505 pos += hd.epoch_bits;
6507 }
else if (rec->header.record_type == SUBORDINATE_STATION) {
6508 rec->level_units = bit_unpack(buf, pos, hd.level_unit_bits);
6509 pos += hd.level_unit_bits;
6511 rec->direction_units = bit_unpack(buf, pos, hd.dir_unit_bits);
6512 pos += hd.dir_unit_bits;
6515 pos += hd.level_unit_bits;
6517 rec->min_time_add = signed_bit_unpack(buf, pos, hd.time_bits);
6518 pos += hd.time_bits;
6520 temp_int = signed_bit_unpack(buf, pos, hd.level_add_bits);
6521 rec->min_level_add = (NV_FLOAT32)temp_int / hd.level_add_scale;
6522 pos += hd.level_add_bits;
6525 temp_int = signed_bit_unpack(buf, pos, hd.level_multiply_bits);
6526 rec->min_level_multiply =
6527 (NV_FLOAT32)temp_int / hd.level_multiply_scale;
6528 pos += hd.level_multiply_bits;
6531 pos += hd.level_add_bits;
6533 rec->min_direction = bit_unpack(buf, pos, hd.direction_bits);
6534 pos += hd.direction_bits;
6536 rec->max_time_add = signed_bit_unpack(buf, pos, hd.time_bits);
6537 pos += hd.time_bits;
6539 temp_int = signed_bit_unpack(buf, pos, hd.level_add_bits);
6540 rec->max_level_add = (NV_FLOAT32)temp_int / hd.level_add_scale;
6541 pos += hd.level_add_bits;
6544 temp_int = signed_bit_unpack(buf, pos, hd.level_multiply_bits);
6545 rec->max_level_multiply =
6546 (NV_FLOAT32)temp_int / hd.level_multiply_scale;
6547 pos += hd.level_multiply_bits;
6550 pos += hd.level_add_bits;
6552 rec->max_direction = bit_unpack(buf, pos, hd.direction_bits);
6553 pos += hd.direction_bits;
6555 rec->flood_begins = signed_bit_unpack(buf, pos, hd.time_bits);
6556 pos += hd.time_bits;
6558 rec->ebb_begins = signed_bit_unpack(buf, pos, hd.time_bits);
6559 pos += hd.time_bits;
6567 rec->country = bit_unpack(buf, pos, hd.country_bits);
6568 pos += hd.country_bits;
6570 unpack_string(buf, bufsize, &pos, rec->source, ONELINER_LENGTH,
6573 rec->restriction = bit_unpack(buf, pos, hd.restriction_bits);
6574 pos += hd.restriction_bits;
6576 unpack_string(buf, bufsize, &pos, rec->comments, MONOLOGUE_LENGTH,
6578 unpack_string(buf, bufsize, &pos, rec->notes, MONOLOGUE_LENGTH,
6581 rec->legalese = bit_unpack(buf, pos, hd.legalese_bits);
6582 pos += hd.legalese_bits;
6584 unpack_string(buf, bufsize, &pos, rec->station_id_context,
6585 ONELINER_LENGTH,
"station_id_context field");
6586 unpack_string(buf, bufsize, &pos, rec->station_id, ONELINER_LENGTH,
6587 "station_id field");
6589 rec->date_imported = bit_unpack(buf, pos, hd.date_bits);
6590 pos += hd.date_bits;
6592 unpack_string(buf, bufsize, &pos, rec->xfields, MONOLOGUE_LENGTH,
6595 rec->direction_units = bit_unpack(buf, pos, hd.dir_unit_bits);
6596 pos += hd.dir_unit_bits;
6598 rec->min_direction = bit_unpack(buf, pos, hd.direction_bits);
6599 pos += hd.direction_bits;
6601 rec->max_direction = bit_unpack(buf, pos, hd.direction_bits);
6602 pos += hd.direction_bits;
6604 rec->level_units = bit_unpack(buf, pos, hd.level_unit_bits);
6606 rec->units = rec->level_units;
6608 pos += hd.level_unit_bits;
6610 if (rec->header.record_type == REFERENCE_STATION) {
6611 temp_int = signed_bit_unpack(buf, pos, hd.datum_offset_bits);
6612 rec->datum_offset = (NV_FLOAT32)temp_int / hd.datum_offset_scale;
6613 pos += hd.datum_offset_bits;
6615 rec->datum = bit_unpack(buf, pos, hd.datum_bits);
6616 pos += hd.datum_bits;
6618 rec->zone_offset = signed_bit_unpack(buf, pos, hd.time_bits);
6619 pos += hd.time_bits;
6621 rec->expiration_date = bit_unpack(buf, pos, hd.date_bits);
6622 pos += hd.date_bits;
6624 rec->months_on_station =
6625 bit_unpack(buf, pos, hd.months_on_station_bits);
6626 pos += hd.months_on_station_bits;
6628 rec->last_date_on_station = bit_unpack(buf, pos, hd.date_bits);
6629 pos += hd.date_bits;
6631 rec->confidence = bit_unpack(buf, pos, hd.confidence_value_bits);
6632 pos += hd.confidence_value_bits;
6634 for (i = 0; i < hd.pub.constituents; ++i) {
6635 rec->amplitude[i] = 0.0;
6636 rec->epoch[i] = 0.0;
6639 count = bit_unpack(buf, pos, hd.constituent_bits);
6640 pos += hd.constituent_bits;
6642 for (i = 0; i < count; ++i) {
6643 j = bit_unpack(buf, pos, hd.constituent_bits);
6644 pos += hd.constituent_bits;
6647 (NV_FLOAT32)bit_unpack(buf, pos, hd.amplitude_bits) /
6649 pos += hd.amplitude_bits;
6652 (NV_FLOAT32)bit_unpack(buf, pos, hd.epoch_bits) / hd.epoch_scale;
6653 pos += hd.epoch_bits;
6655 }
else if (rec->header.record_type == SUBORDINATE_STATION) {
6656 rec->min_time_add = signed_bit_unpack(buf, pos, hd.time_bits);
6657 pos += hd.time_bits;
6659 temp_int = signed_bit_unpack(buf, pos, hd.level_add_bits);
6660 rec->min_level_add = (NV_FLOAT32)temp_int / hd.level_add_scale;
6661 pos += hd.level_add_bits;
6664 temp_int = bit_unpack(buf, pos, hd.level_multiply_bits);
6665 rec->min_level_multiply =
6666 (NV_FLOAT32)temp_int / hd.level_multiply_scale;
6667 pos += hd.level_multiply_bits;
6669 rec->max_time_add = signed_bit_unpack(buf, pos, hd.time_bits);
6670 pos += hd.time_bits;
6672 temp_int = signed_bit_unpack(buf, pos, hd.level_add_bits);
6673 rec->max_level_add = (NV_FLOAT32)temp_int / hd.level_add_scale;
6674 pos += hd.level_add_bits;
6677 temp_int = bit_unpack(buf, pos, hd.level_multiply_bits);
6678 rec->max_level_multiply =
6679 (NV_FLOAT32)temp_int / hd.level_multiply_scale;
6680 pos += hd.level_multiply_bits;
6682 rec->flood_begins = signed_bit_unpack(buf, pos, hd.time_bits);
6683 pos += hd.time_bits;
6685 rec->ebb_begins = signed_bit_unpack(buf, pos, hd.time_bits);
6686 pos += hd.time_bits;
6696 assert(pos <= bufsize * 8);
6720NV_INT32 read_tide_record(NV_INT32 num,
TIDE_RECORD *rec) {
6726 "libtcd error: attempt to access database when database not open\n");
6730 if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
return -1;
6733 bufsize = tindex[num].record_size;
6734 if ((buf = (NV_U_BYTE *)calloc(bufsize,
sizeof(NV_U_BYTE))) == NULL) {
6735 perror(
"Allocating read_tide_record buffer");
6739 current_record = num;
6740 require(fseek(fp, tindex[num].address, SEEK_SET) == 0);
6741 chk_fread(buf, tindex[num].record_size, 1, fp);
6742 unpack_tide_record(buf, bufsize, rec);
6769 "libtcd error: attempt to access database when database not open\n");
6774 if (!check_tide_record(rec))
return NVFalse;
6776 fseek(fp, hd.end_of_file, SEEK_SET);
6780 rec->header.record_number = hd.pub.number_of_records++;
6782 if (write_tide_record(-1, rec)) {
6784 tindex, hd.pub.number_of_records *
sizeof(
TIDE_INDEX))) == NULL) {
6785 perror(
"Allocating more index records");
6789 tindex[rec->header.record_number].address = pos;
6790 tindex[rec->header.record_number].record_size = rec->header.record_size;
6791 tindex[rec->header.record_number].record_type = rec->header.record_type;
6792 tindex[rec->header.record_number].reference_station =
6793 rec->header.reference_station;
6794 assert(rec->header.tzfile >= 0);
6795 tindex[rec->header.record_number].tzfile = rec->header.tzfile;
6796 tindex[rec->header.record_number].lat =
6797 NINT(rec->header.latitude * hd.latitude_scale);
6798 tindex[rec->header.record_number].lon =
6799 NINT(rec->header.longitude * hd.longitude_scale);
6801 if ((tindex[rec->header.record_number].name = (NV_CHAR *)calloc(
6802 strlen(rec->header.name) + 1,
sizeof(NV_CHAR))) == NULL) {
6803 perror(
"Allocating index name memory");
6807 strcpy(tindex[rec->header.record_number].name, rec->header.name);
6810 hd.end_of_file = pos;
6814 if (db) *db = hd.pub;
6843 NV_INT32 i, newrecnum, *map;
6844 NV_U_BYTE **allrecs_packed;
6847 LOG_ERROR (
"libtcd error: attempt to access database when database not open\n");
6852 if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
return NVFalse;
6856 if (!(map = (NV_INT32 *) malloc (hd.pub.number_of_records *
sizeof(NV_INT32)))) {
6857 perror (
"libtcd: delete_tide_record: can't malloc");
6860 if (!(allrecs_packed = (NV_U_BYTE **) malloc (hd.pub.number_of_records *
sizeof(NV_U_BYTE*)))) {
6861 perror (
"libtcd: delete_tide_record: can't malloc");
6869 require (fseek (fp, tindex[0].address, SEEK_SET) == 0);
6870 for (newrecnum=0,i=0; i<(NV_INT32)hd.pub.number_of_records; ++i) {
6871 assert (ftell(fp) == tindex[i].address);
6872 if (i == num || (tindex[i].record_type == SUBORDINATE_STATION && tindex[i].reference_station == num)) {
6874 allrecs_packed[i] = NULL;
6875 require (fseek (fp, tindex[i].record_size, SEEK_CUR) == 0);
6877 map[i] = newrecnum++;
6878 if (!(allrecs_packed[i] = (NV_U_BYTE *) malloc (tindex[i].record_size))) {
6879 perror (
"libtcd: delete_tide_record: can't malloc");
6880 for (--i; i>=0; --i)
6881 free (allrecs_packed[i]);
6882 free (allrecs_packed);
6886 chk_fread (allrecs_packed[i], tindex[i].record_size, 1, fp);
6892 require (fseek (fp, tindex[0].address, SEEK_SET) == 0);
6893 require (ftruncate (fileno(fp), tindex[0].address) == 0);
6895 for (i=0; i<(NV_INT32)hd.pub.number_of_records; ++i)
6897 if (tindex[i].record_type == SUBORDINATE_STATION) {
6898 assert (tindex[i].reference_station >= 0);
6899 assert (tindex[i].reference_station <= (NV_INT32)hd.pub.number_of_records);
6900 if (map[tindex[i].reference_station] != tindex[i].reference_station) {
6903 unpack_tide_record (allrecs_packed[i], tindex[i].record_size, &rec);
6904 free (allrecs_packed[i]);
6905 rec.header.reference_station = map[tindex[i].reference_station];
6906 pack_tide_record (&rec, &(allrecs_packed[i]), &(tindex[i].record_size));
6909 chk_fwrite (allrecs_packed[i], tindex[i].record_size, 1, fp);
6910 free (allrecs_packed[i]);
6915 free (allrecs_packed);
6921 hd.end_of_file = ftell(fp);
6922 hd.pub.number_of_records = newrecnum;
6925 open_tide_db (filename);
6954NV_BOOL update_tide_record(NV_INT32 num,
TIDE_RECORD *rec)
6961 NV_U_BYTE *
block = NULL;
6965 "libtcd error: attempt to access database when database not open\n");
6970 if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
return NVFalse;
6972 if (!check_tide_record(rec))
return NVFalse;
6975 read_tide_record(num, &tmp_rec);
6976 if (rec->header.record_size != tmp_rec.header.record_size) {
6984 size = hd.end_of_file - pos;
6989 if ((
block = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
6990 perror(
"Allocating block");
6993 chk_fread(
block, size, 1, fp);
6997 write_tide_record(num, rec);
7001 chk_fwrite(
block, size, 1, fp);
7005 hd.end_of_file = ftell(fp);
7009 open_tide_db(filename);
7014 write_tide_record(num, rec);
7017 tindex[num].record_size = rec->header.record_size;
7018 tindex[num].record_type = rec->header.record_type;
7019 tindex[num].reference_station = rec->header.reference_station;
7020 tindex[num].tzfile = rec->header.tzfile;
7021 tindex[num].lat = NINT(rec->header.latitude * hd.latitude_scale);
7022 tindex[num].lon = NINT(rec->header.longitude * hd.longitude_scale);
7027 if (strcmp(tindex[num].name, rec->header.name) != 0) {
7028 free(tindex[num].name);
7030 (NV_CHAR *)calloc(strlen(rec->header.name) + 1,
sizeof(NV_CHAR));
7031 strcpy(tindex[num].name, rec->header.name);
7036 if (db) *db = hd.pub;
7073 NV_INT32 m2, s2, k1, o1;
7074 NV_FLOAT32 epoch_m2, epoch_s2, epoch_k1, epoch_o1;
7077 require((m2 = find_constituent(
"M2")) >= 0);
7078 require((s2 = find_constituent(
"S2")) >= 0);
7079 require((k1 = find_constituent(
"K1")) >= 0);
7080 require((o1 = find_constituent(
"O1")) >= 0);
7082 if (rec->amplitude[m2] == 0.0 || rec->amplitude[s2] == 0.0 ||
7083 rec->amplitude[k1] == 0.0 || rec->amplitude[o1] == 0.0)
7086 epoch_m2 = rec->epoch[m2];
7087 epoch_s2 = rec->epoch[s2];
7088 epoch_k1 = rec->epoch[k1];
7089 epoch_o1 = rec->epoch[o1];
7091 for (i = 0; i < hd.pub.constituents; ++i) {
7092 if (rec->amplitude[i] == 0.0 && rec->epoch[i] == 0.0) {
7093 for (j = 0; j < INFERRED_SEMI_DIURNAL_COUNT; ++j) {
7094 if (!strcmp(inferred_semi_diurnal[j], get_constituent(i))) {
7098 (semi_diurnal_coeff[j] / coeff[0]) * rec->amplitude[m2];
7100 if (fabs((NV_FLOAT64)(epoch_s2 - epoch_m2)) > 180.0) {
7101 if (epoch_s2 < epoch_m2) {
7107 rec->epoch[i] = epoch_m2 + ((hd.speed[i] - hd.speed[m2]) /
7108 (hd.speed[s2] - hd.speed[m2])) *
7109 (epoch_s2 - epoch_m2);
7113 for (j = 0; j < INFERRED_DIURNAL_COUNT; ++j) {
7114 if (!strcmp(inferred_diurnal[j], get_constituent(i))) {
7118 (diurnal_coeff[j] / coeff[1]) * rec->amplitude[o1];
7120 if (fabs((NV_FLOAT64)(epoch_k1 - epoch_o1)) > 180.0) {
7121 if (epoch_k1 < epoch_o1) {
7127 rec->epoch[i] = epoch_o1 + ((hd.speed[i] - hd.speed[o1]) /
7128 (hd.speed[k1] - hd.speed[o1])) *
7129 (epoch_k1 - epoch_o1);
7144static NV_U_BYTE mask[8] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe},
7145 notmask[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
7184NV_U_INT32 calculate_bits(NV_U_INT32 value) {
7185 NV_U_INT32 bits = 32;
7186 NV_U_INT32 theBit = 0x80000000;
7188 while (value < theBit) {
7223void bit_pack(NV_U_BYTE buffer[], NV_U_INT32 start, NV_U_INT32 numbits,
7225 NV_INT32 start_byte, end_byte, start_bit, end_bit, i;
7227 i = start + numbits;
7233 start_byte = start >> 3;
7240 start_bit = start & 7;
7245 i = end_byte - start_byte - 1;
7249 if (start_byte == end_byte) {
7254 buffer[start_byte] &= mask[start_bit] | notmask[end_bit];
7260 buffer[start_byte] |=
7261 (value << (8 - end_bit)) & (notmask[start_bit] & mask[end_bit]);
7267#pragma GCC diagnostic push
7268#pragma GCC diagnostic ignored "-Warray-bounds"
7273 buffer[start_byte] &= mask[start_bit];
7281 buffer[start_byte++] |=
7282 (value >> (numbits - (8 - start_bit))) & notmask[start_bit];
7289 buffer[start_byte] &= 0;
7293 buffer[start_byte++] |= (value >> ((i << 3) + end_bit)) & 255;
7298 buffer[start_byte] &= notmask[end_bit];
7304 buffer[start_byte] |= (value << (8 - end_bit));
7305#pragma GCC diagnostic pop
7335NV_U_INT32 bit_unpack(NV_U_BYTE buffer[], NV_U_INT32 start,
7336 NV_U_INT32 numbits) {
7337 NV_INT32 start_byte, end_byte, start_bit, end_bit, i;
7340 i = start + numbits;
7346 start_byte = start >> 3;
7353 start_bit = start & 7;
7358 i = end_byte - start_byte - 1;
7362 if (start_byte == end_byte) {
7366 (NV_U_INT32)buffer[start_byte] & (notmask[start_bit] & mask[end_bit]);
7370 value >>= (8 - end_bit);
7379 value = (NV_U_INT32)(buffer[start_byte++] & notmask[start_bit])
7380 << (numbits - (8 - start_bit));
7387 value += (NV_U_INT32)buffer[start_byte++] << ((i << 3) + end_bit);
7392 if (mask[end_bit]) {
7394 (NV_U_INT32)(buffer[start_byte] & mask[end_bit]) >> (8 - end_bit);
7427NV_INT32 signed_bit_unpack(NV_U_BYTE buffer[], NV_U_INT32 start,
7428 NV_U_INT32 numbits) {
7429 static NV_INT32 extend_mask = 0x7fffffff;
7433 assert(numbits > 0);
7435 value = bit_unpack(buffer, start, numbits);
7437 if (value & (1 << (numbits - 1))) value |= (extend_mask << numbits);
Represents an index entry for tidal and current data.
int have_offsets
Flag indicating presence of time/height offsets.
time_t epoch
Epoch time for the station.
int IDX_time_zone
Station timezone offset from UTC (in minutes)
char IDX_type
Entry type identifier "TCtcIUu".
int num_nodes
Number of nodes in harmonic analysis.
float IDX_lt_off
Low tide height offset.
TCDataSource * pDataSource
Pointer to the associated data source.
float IDX_lt_mpy
Low tide height multiplier.
int Valid15
Validity flag for 15-minute interval data.
time_t recent_high_time
Time of the most recent high tide.
int epoch_year
Year of the epoch.
int IDX_flood_dir
Flood current direction (in degrees)
int IDX_Useable
Flag indicating if the entry is usable.
char IDX_station_name[MAXNAMELEN]
Name of the tidal or current station.
float recent_low_level
Most recently calculated low tide level.
int station_tz_offset
Offset in seconds to convert from harmonic data (epochs) to the station time zone.
double max_amplitude
Maximum tidal amplitude.
int first_year
First year of valid data.
double * m_work_buffer
Work buffer for calculations.
int IDX_ht_time_off
High tide time offset (in minutes)
float Dir15
Direction for 15-minute interval data.
float recent_high_level
Most recently calculated high tide level.
double ** m_cst_nodes
2D array of constituent nodes
int IDX_ebb_dir
Ebb current direction (in degrees)
double ** m_cst_epochs
2D array of constituent epochs
float IDX_ht_mpy
High tide height multiplier.
int current_depth
Depth for current stations.
double IDX_lat
Latitude of the station (in degrees, +North)
double IDX_lon
Longitude of the station (in degrees, +East)
bool Ret15
Return flag for 15-minute interval data.
bool b_skipTooDeep
Flag to skip processing if depth exceeds limit.
int num_epochs
Number of epochs in harmonic data.
double * m_cst_speeds
Array of constituent speeds.
Station_Data * pref_sta_data
Pointer to the reference station data.
int IDX_lt_time_off
Low tide time offset (in minutes)
time_t recent_highlow_calc_time
Timestamp of the most recent high/low calculation.
int num_csts
Number of harmonic constituents.
time_t recent_low_time
Time of the most recent low tide.
float IDX_ht_off
High tide height offset.
int IDX_rec_num
Record number for multiple entries with same name.
float Value15
Value for 15-minute interval data.
General purpose GUI support.
Enhanced logging interface on top of wx/log.h.
std::string tolower(const std::string &input)
Return copy of s with all characters converted to lower case.
wxDateTime toUsrDateTime(const wxDateTime ts, const int format, const double lon)
Converts a timestamp from UTC to the user's preferred time format.
Runtime representation of a plugin block.
TCMgr * ptcmgr
Global instance.
double BOGUS_amplitude(double mpy, IDX_entry *pIDX)
BOGUS amplitude stuff - Added mgh For knots^2 current stations, returns square root of (value * ampli...
Tide and Current Manager @TODO Add original author copyright.