1 /***************************************************************************
2  *
3  * Project:  OpenCPN
4  * Purpose:  Tide and Current Manager
5  * Author:   David Register
6  *
7  ***************************************************************************
8  *   Copyright (C) 2010 by David S. Register                               *
9  *                                                                         *
10  *   This program is free software; you can redistribute it and/or modify  *
11  *   it under the terms of the GNU General Public License as published by  *
12  *   the Free Software Foundation; either version 2 of the License, or     *
13  *   (at your option) any later version.                                   *
14  *                                                                         *
15  *   This program is distributed in the hope that it will be useful,       *
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  *   GNU General Public License for more details.                          *
19  *                                                                         *
20  *   You should have received a copy of the GNU General Public License     *
21  *   along with this program; if not, write to the                         *
22  *   Free Software Foundation, Inc.,                                       *
23  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA.         *
24  **************************************************************************/
25 
26 #include "wx/wxprec.h"
27 #ifndef  WX_PRECOMP
28 #include "wx/wx.h"
29 #endif //precompiled headers
30 #include <wx/datetime.h>
31 
32 #include <stdlib.h>
33 #include <math.h>
34 #include <time.h>
35 
36 #include "chart1.h"
37 #include "dychart.h"
38 #include "tcmgr.h"
39 #include "georef.h"
40 #include "logger.h"
41 
42 //-----------------------------------------------------------------------------------
43 //    TIDELIB
44 //-----------------------------------------------------------------------------------
45 
46 //      Static variables for the TIDELIB
47 
48 time_t s_next_epoch      = TIDE_BAD_TIME; /* next years newyears */
49 time_t s_this_epoch      = TIDE_BAD_TIME; /* this years newyears */
50 int    s_this_year       = -1;
51 
52 double time2dt_tide (time_t t, int deriv, IDX_entry *pIDX);
53 int yearoftimet (time_t t);
54 void happy_new_year (IDX_entry *pIDX, int new_year);
55 void set_epoch (IDX_entry *pIDX, int year);
56 
time2tide(time_t t,IDX_entry * pIDX)57 double time2tide (time_t t, IDX_entry *pIDX)
58 {
59     return time2dt_tide(t, 0, pIDX);
60 }
61 
62 
63 
64 /** BOGUS amplitude stuff - Added mgh
65  * For knots^2 current stations, returns square root of (value * amplitude),
66  * For normal stations, returns value * amplitude */
67 
BOGUS_amplitude(double mpy,IDX_entry * pIDX)68 double BOGUS_amplitude(double mpy, IDX_entry *pIDX)
69 {
70     Station_Data *pmsd = pIDX->pref_sta_data;
71 
72     if (!pmsd->have_BOGUS)                                // || !convert_BOGUS)   // Added mgh
73         return(mpy * pIDX->max_amplitude);
74     else {
75         if (mpy >= 0.0)
76             return( sqrt( mpy * pIDX->max_amplitude));
77         else
78             return(-sqrt(-mpy * pIDX->max_amplitude));
79     }
80 }
81 
82 /* Calculate the denormalized tide. */
time2atide(time_t t,IDX_entry * pIDX)83 double time2atide (time_t t, IDX_entry *pIDX)
84 {
85     return BOGUS_amplitude(time2tide(t, pIDX), pIDX) + pIDX->pref_sta_data->DATUM;
86 }
87 
88 
89 /* Next high tide, low tide, transition of the mark level, or some
90  *   combination.
91  *       Bit      Meaning
92  *        0       low tide
93  *        1       high tide
94  *        2       falling transition
95  *        3       rising transition
96  */
next_big_event(time_t * tm,IDX_entry * pIDX)97 int next_big_event (time_t *tm, IDX_entry *pIDX)
98 {
99     double p, q;
100     int flags = 0, slope = 0;
101     p = time2atide (*tm, pIDX);
102     *tm += 60;
103     q = time2atide (*tm, pIDX);
104     *tm += 60;
105     if (p < q)
106         slope = 1;
107     while (1) {
108         if ((slope == 1 && q < p) || (slope == 0 && p < q)) {
109             /* Tide event */
110             flags |= (1 << slope);
111         }
112         /* Modes in which to return mark transitions: */
113         /*    -text (no -graph)   */
114         /*    -graph (no -text)   */
115         /*    -ppm                */
116         /*    -gif                */
117         /*    -ps                 */
118 
119 
120         //    if (mark && ((text && !graphmode) || (!text && graphmode)
121         //    || ppm || gif || ps))
122         //      int marklev = 0;
123 #if (0)
124         if(0)
125             if ((p > marklev && q <= marklev) || (p < marklev && q >= marklev)) {
126                 /* Transition event */
127                 if (p < q)
128                     flags |= 8;
129                 else
130                     flags |= 4;
131                 if (!(flags & 3)) {
132                     /* If we're incredibly unlucky, we could miss a tide event if we
133                      *                       don't check for it here:
134                      *
135                      *                                       . <----   Value that would be returned
136                      *                                  -----------    Mark level
137                      *                                .           .
138                      */
139                     p = q;
140                     q = time2atide (*tm, pIDX);
141                     if ((slope == 1 && q < p) || (slope == 0 && p < q)) {
142                         /* Tide event */
143                         flags |= (1 << slope);
144                     }
145                 }
146             }
147 #endif
148 
149         if (flags) {
150             *tm -= 60;
151             /* Don't back up over a transition event, but do back up to where the
152              *               tide changed if possible.  If they happen at the same time, then
153              *               we're off by a minute on the tide, but if we back it up it will
154              *               get snagged on the transition event over and over. */
155             if (flags < 4)
156                 *tm -= 60;
157             return flags;
158         }
159         p = q;
160         q = time2atide (*tm, pIDX);
161         *tm += 60;
162     }
163 }
164 
165 
166 
167 /* Estimate the normalized mean tide level around a particular time by
168  *   summing only the long-term constituents. */
169 /* Does not do any blending around year's end. */
170 /* This is used only by time2asecondary for finding the mean tide level */
time2mean(time_t t,IDX_entry * pIDX)171 double time2mean (time_t t, IDX_entry *pIDX)
172 {
173     double tide = 0.0;
174     int a;
175     int new_year = yearoftimet (t);
176     if (pIDX->epoch_year != new_year)
177         happy_new_year (pIDX, new_year);
178 
179     for (a=0; a<pIDX->num_csts; a++) {
180         if (pIDX->m_cst_speeds[a] < 6e-6) {
181             tide += pIDX->m_work_buffer[a] *
182                     cos (pIDX->m_cst_speeds[a] * ((long)(t - pIDX->epoch) + pIDX->pref_sta_data->meridian) +
183                     pIDX->m_cst_epochs[a][pIDX->epoch_year-pIDX->first_year] - pIDX->pref_sta_data->epoch[a]);
184         }
185     }
186 
187     return tide;
188 }
189 
190 
191 
192 /* If offsets are in effect, interpolate the 'corrected' denormalized
193  * tide.  The normalized is derived from this, instead of the other way
194  * around, because the application of height offsets requires the
195  * denormalized tide. */
time2asecondary(time_t t,IDX_entry * pIDX)196 double time2asecondary (time_t t, IDX_entry *pIDX) {
197 
198     time_t tadj = t + pIDX->station_tz_offset;
199 
200     /* Get rid of the normals. */
201     if (!(pIDX->have_offsets))
202         return time2atide (tadj, pIDX);
203 
204     {
205         /* Intervalwidth of 14 (was originally 13) failed on this input:
206          *        -location Dublon -hloff +0.0001 -gstart 1997:09:10:00:00 -raw 1997:09:15:00:00
207          */
208 #define intervalwidth 15
209 #define stretchfactor 3
210 
211         static time_t lowtime=0, hightime=0;
212         static double lowlvl, highlvl; /* Normalized tide levels for MIN, MAX */
213         time_t T;  /* Adjusted t */
214         double S, Z, HI, HS, magicnum;
215         time_t interval = 3600 * intervalwidth;
216         long difflow, diffhigh;
217         int badlowflag=0, badhighflag=0;
218 
219 
220         /* Algorithm by Jean-Pierre Lapointe (scipur@collegenotre-dame.qc.ca) */
221         /* as interpreted, munged, and implemented by DWF */
222 
223         /* This is the initial guess (average of time offsets) */
224         //    T = t - (httimeoff + lttimeoff) / 2;
225         T = tadj - (pIDX->IDX_ht_time_off * 60 + pIDX->IDX_lt_time_off * 60) / 2;
226         /* The usage of an estimate of mean tide level here is to correct
227          *           for seasonal changes in tide level.  Previously I had simply used
228          *           the zero of the tide function as the mean, but this gave bad
229          *           results around summer and winter for locations with large seasonal
230          *           variations. */
231 //        printf("-----time2asecondary  %ld %ld %d %d\n", t, T, pIDX->IDX_ht_time_off ,pIDX->IDX_lt_time_off);
232 
233         Z = time2mean(T, pIDX);
234         S = time2tide(T, pIDX) - Z;
235 
236         /* Find MAX and MIN.  I use the highest high tide and the lowest
237          *           low tide over a 26 hour period, but I allow the interval to stretch
238          *           a lot if necessary to avoid creating discontinuities.  The
239          *           heuristic used is not perfect but will hopefully be good enough.
240          *
241          *           It is an assumption in the algorithm that the tide level will
242          *           be above the mean tide level for MAX and below it for MIN.  A
243          *           changeover occurs at mean tide level.  It would be nice to
244          *           always use the two tides that immediately bracket T and to put
245          *           the changeover at mid tide instead of always at mean tide
246          *           level, since this would eliminate much of the inaccuracy.
247          *           Unfortunately if you change the location of the changeover it
248          *           causes the tide function to become discontinuous.
249          *
250          *           Now that I'm using time2mean, the changeover does move, but so
251          *           slowly that it makes no difference.
252          */
253 
254         if (lowtime < T)
255             difflow = T - lowtime;
256         else
257             difflow = lowtime - T;
258         if (hightime < T)
259             diffhigh = T - hightime;
260         else
261             diffhigh = hightime - T;
262 
263         /* Update MIN? */
264         if (difflow > interval * stretchfactor)
265             badlowflag = 1;
266         if (badlowflag || (difflow > interval && S > 0)) {
267             time_t tt;
268             double tl;
269             tt = T - interval;
270             next_big_event (&tt, pIDX);
271             lowlvl = time2tide (tt, pIDX);
272             lowtime = tt;
273             while (tt < T + interval) {
274                 next_big_event (&tt, pIDX);
275                 tl = time2tide (tt, pIDX);
276                 if (tl < lowlvl && tt < T + interval) {
277                     lowlvl = tl;
278                     lowtime = tt;
279                 }
280             }
281         }
282         /* Update MAX? */
283         if (diffhigh > interval * stretchfactor)
284             badhighflag = 1;
285         if (badhighflag || (diffhigh > interval && S < 0)) {
286             time_t tt;
287             double tl;
288             tt = T - interval;
289             next_big_event (&tt, pIDX);
290             highlvl = time2tide (tt, pIDX);
291             hightime = tt;
292             while (tt < T + interval) {
293                 next_big_event (&tt, pIDX);
294                 tl = time2tide (tt, pIDX);
295                 if (tl > highlvl && tt < T + interval) {
296                     highlvl = tl;
297                     hightime = tt;
298                 }
299             }
300         }
301 
302 #if 0
303         /* UNFORTUNATELY there are times when the tide level NEVER CROSSES
304          *           THE MEAN for extended periods of time.  ARRRGH!  */
305         if (lowlvl >= 0.0)
306             lowlvl = -1.0;
307         if (highlvl <= 0.0)
308             highlvl = 1.0;
309 #endif
310         /* Now that I'm using time2mean, I should be guaranteed to get
311          *           an appropriate low and high. */
312 
313 
314         /* Improve the initial guess. */
315         if (S > 0)
316             magicnum = 0.5 * S / fabs(highlvl - Z);
317         else
318             magicnum = 0.5 * S / fabs(lowlvl - Z);
319         //    T = T - magicnum * (httimeoff - lttimeoff);
320         T = T - (time_t)(magicnum * ((pIDX->IDX_ht_time_off * 60) - (pIDX->IDX_lt_time_off * 60)));
321         HI = time2tide(T, pIDX);
322 
323         //    Correct the amplitude offsets for BOGUS knot^2 units
324         double ht_off, lt_off;
325         if (pIDX->pref_sta_data->have_BOGUS)
326         {
327             ht_off = pIDX->IDX_ht_off * pIDX->IDX_ht_off;         // Square offset in kts to adjust for kts^2
328             lt_off = pIDX->IDX_lt_off * pIDX->IDX_lt_off;
329         }
330         else
331         {
332             ht_off = pIDX->IDX_ht_off;
333             lt_off = pIDX->IDX_lt_off;
334         }
335 
336 
337         /* Denormalize and apply the height offsets. */
338         HI = BOGUS_amplitude(HI, pIDX) + pIDX->pref_sta_data->DATUM;
339         {
340             double RH=1.0, RL=1.0, HH=0.0, HL=0.0;
341             RH = pIDX->IDX_ht_mpy;
342             HH = ht_off;
343             RL = pIDX->IDX_lt_mpy;
344             HL = lt_off;
345 
346             /* I patched the usage of RH and RL to avoid big ugly
347              *            discontinuities when they are not equal.  -- DWF */
348 
349             HS =  HI * ((RH+RL)/2 + (RH-RL)*magicnum)
350                   + (HH+HL)/2 + (HH-HL)*magicnum;
351         }
352 
353         return HS;
354     }
355 }
356 
357 
358 
359 
360 
361 
362 /*
363  * We will need a function for tidal height as a function of time
364  * which is continuous (and has continuous first and second derivatives)
365  * for all times.
366  *
367  * Since the epochs & multipliers for the tidal constituents change
368  * with the year, the regular time2tide(t) function has small
369  * discontinuities at new years.  These discontinuities really
370  * fry the fast root-finders.
371  *
372  * We will eliminate the new-years discontinuities by smoothly
373  * interpolating (or "blending") between the tides calculated with one
374  * year's coefficients, and the tides calculated with the next year's
375  * coefficients.
376  *
377  * i.e. for times near a new years, we will "blend" a tide
378  * as follows:
379  *
380  * tide(t) = tide(year-1, t)
381  *                  + w((t - t0) / Tblend) * (tide(year,t) - tide(year-1,t))
382  *
383  * Here:  t0 is the time of the nearest new-year.
384  *        tide(year-1, t) is the tide calculated using the coefficients
385  *           for the year just preceding t0.
386  *        tide(year, t) is the tide calculated using the coefficients
387  *           for the year which starts at t0.
388  *        Tblend is the "blending" time scale.  This is set by
389  *           the macro TIDE_BLEND_TIME, currently one hour.
390  *        w(x) is the "blending function", whice varies smoothly
391  *           from 0, for x < -1 to 1 for x > 1.
392  *
393  * Derivatives of the blended tide can be evaluated in terms of derivatives
394  * of w(x), tide(year-1, t), and tide(year, t).  The blended tide is
395  * guaranteed to have as many continuous derivatives as w(x).  */
396 
397 /* time2dt_tide(time_t t, int n)
398  *
399  *   Calculate nth time derivative the normalized tide.
400  *
401  * Notes: This function does not check for changes in year.
402  *  This is important to our algorithm, since for times near
403  *  new years, we interpolate between the tides calculated
404  *  using one years coefficients, and the next years coefficients.
405  *
406  *  Except for this detail, time2dt_tide(t,0) should return a value
407  *  identical to time2tide(t).
408  */
_time2dt_tide(time_t t,int deriv,IDX_entry * pIDX)409 double _time2dt_tide (time_t t, int deriv, IDX_entry *pIDX)
410 {
411     double dt_tide = 0.0;
412     int a, b;
413     double term, tempd;
414 
415     tempd = M_PI / 2.0 * deriv;
416     for (a=0; a<pIDX->num_csts; a++)
417     {
418         term = pIDX->m_work_buffer[a] *
419                cos(tempd +
420                    pIDX->m_cst_speeds[a] * ((long)(t - pIDX->epoch) + pIDX->pref_sta_data->meridian) +
421                    pIDX->m_cst_epochs[a][pIDX->epoch_year-pIDX->first_year] - pIDX->pref_sta_data->epoch[a]);
422         for (b = deriv; b > 0; b--)
423             term *= pIDX->m_cst_speeds[a];
424         dt_tide += term;
425     }
426     return dt_tide;
427 }
428 
429 /* blend_weight (double x, int deriv)
430  *
431  * Returns the value nth derivative of the "blending function" w(x):
432  *
433  *   w(x) =  0,     for x <= -1
434  *
435  *   w(x) =  1/2 + (15/16) x - (5/8) x^3 + (3/16) x^5,
436  *                  for  -1 < x < 1
437  *
438  *   w(x) =  1,     for x >= 1
439  *
440  * This function has the following desirable properties:
441  *
442  *    w(x) is exactly either 0 or 1 for |x| > 1
443  *
444  *    w(x), as well as its first two derivatives are continuous for all x.
445  */
446 static double
blend_weight(double x,int deriv)447 blend_weight (double x, int deriv)
448 {
449     double x2 = x * x;
450 
451     if (x2 >= 1.0)
452         return deriv == 0 && x > 0.0 ? 1.0 : 0.0;
453 
454     switch (deriv) {
455     case 0:
456         return ((3.0 * x2 -10.0) * x2 + 15.0) * x / 16.0 + 0.5;
457     case 1:
458         return ((x2 - 2.0) * x2 + 1.0) * (15.0/16.0);
459     case 2:
460         return (x2 - 1.0) * x * (15.0/4.0);
461     }
462     return(0); // mgh+ to get rid of compiler warning
463 }
464 
465 /*
466  * This function does the actual "blending" of the tide
467  * and its derivatives.
468  */
blend_tide(time_t t,unsigned int deriv,int first_year,double blend,IDX_entry * pIDX)469 double blend_tide (time_t t, unsigned int deriv, int first_year, double blend, IDX_entry *pIDX)
470 {
471     double        fl[TIDE_MAX_DERIV + 1];
472     double        fr[TIDE_MAX_DERIV + 1];
473     double *      fp      = fl;
474     double        w[TIDE_MAX_DERIV + 1];
475     double        fact = 1.0;
476     double        f;
477     unsigned int  n;
478 
479 
480     /*
481      * If we are already happy_new_year()ed into one of the two years
482      * of interest, compute that years tide values first.
483      */
484     int year = yearoftimet(t);
485     if (year == first_year + 1)
486         fp = fr;
487     else if (year != first_year)
488         happy_new_year(pIDX, first_year);
489     for (n = 0; n <= deriv; n++)
490         fp[n] = _time2dt_tide(t, n, pIDX);
491 
492     /*
493      * Compute tide values for the other year of interest,
494      *  and the needed values of w(x) and its derivatives.
495      */
496     if (fp == fl)
497     {
498         happy_new_year(pIDX, first_year + 1);
499         fp = fr;
500     }
501     else
502     {
503         happy_new_year(pIDX, first_year);
504         fp = fl;
505     }
506     for (n = 0; n <= deriv; n++)
507     {
508         fp[n] = _time2dt_tide(t, n, pIDX);
509         w[n] = blend_weight(blend, n);
510     }
511 
512     /*
513      * Do the blending.
514      */
515 
516 
517     f = fl[deriv];
518     for (n = 0; n <= deriv; n++)
519     {
520         f += fact * w[n] * (fr[deriv-n] - fl[deriv-n]);
521         fact *= (double)(deriv - n)/(n+1) * (1.0/TIDE_BLEND_TIME);
522     }
523     printf(" %ld  %g     %g %g %g\n", (long)t, blend, fr[0], fl[0], f);
524     return f;
525 }
526 
time2dt_tide(time_t t,int deriv,IDX_entry * pIDX)527 double  time2dt_tide (time_t t, int deriv, IDX_entry *pIDX)
528 {
529     int           new_year;
530     int yott = yearoftimet( t );
531     new_year = yott;
532 
533     /* Make sure our values of next_epoch and epoch are up to date. */
534     if (new_year != s_this_year)
535     {
536         if (new_year + 1 < pIDX->first_year + pIDX->num_epochs)
537         {
538             set_epoch(pIDX, new_year + 1);
539             s_next_epoch = pIDX->epoch;
540         }
541         else
542             s_next_epoch = TIDE_BAD_TIME;
543 
544         happy_new_year(pIDX, s_this_year = new_year);
545         s_this_epoch = pIDX->epoch;
546     }
547 
548 
549     /*
550      * If we're close to either the previous or the next
551      * new years we must blend the two years tides.
552      */
553     if (t - s_this_epoch <= TIDE_BLEND_TIME && s_this_year > pIDX->first_year)
554         return blend_tide(t, deriv,
555                           s_this_year - 1,
556                           (double)(t - s_this_epoch)/TIDE_BLEND_TIME,
557                           pIDX );
558     else if (s_next_epoch - t <= TIDE_BLEND_TIME
559              && s_this_year + 1 < pIDX->first_year + pIDX->num_epochs)
560         return blend_tide(t, deriv,
561                           s_this_year,
562                           -(double)(s_next_epoch - t)/TIDE_BLEND_TIME,
563                           pIDX );
564 
565     /*
566      * Else, we're far enough from newyears to ignore the blending.
567      */
568     if (pIDX->epoch_year != new_year)
569         happy_new_year(pIDX, new_year);
570 
571     return _time2dt_tide(t, deriv, pIDX);
572 }
573 
574 
575 
576 /* Figure out max amplitude over all the years in the node factors table. */
577 /* This function by Geoffrey T. Dairiki */
figure_max_amplitude(IDX_entry * pIDX)578 void figure_max_amplitude (IDX_entry *pIDX)
579 {
580     int       i, a;
581 
582     if (pIDX->max_amplitude == 0.0) {
583         for (i = 0; i < pIDX->num_nodes; i++) {
584             double year_amp = 0.0;
585 
586             for (a=0; a < pIDX->num_csts; a++)
587                 year_amp += pIDX->pref_sta_data->amplitude[a] * pIDX->m_cst_nodes[a][i];
588             if (year_amp > pIDX->max_amplitude)
589                 pIDX->max_amplitude = year_amp;
590         }
591     }
592 }
593 
594 /* Figure out normalized multipliers for constituents for a particular year. */
figure_multipliers(IDX_entry * pIDX,int year)595 void figure_multipliers (IDX_entry *pIDX, int year)
596 {
597     int a;
598 
599     figure_max_amplitude( pIDX );
600     for (a = 0; a < pIDX->num_csts; a++) {
601         pIDX->m_work_buffer[a] = pIDX->pref_sta_data->amplitude[a] * pIDX->m_cst_nodes[a][year-pIDX->first_year] / pIDX->max_amplitude;  // BOGUS_amplitude?
602     }
603 }
604 
605 
606 /* This idiotic function is needed by the new tm2gmt. */
607 #define compare_int(a,b) (((int)(a))-((int)(b)))
compare_tm(struct tm * a,struct tm * b)608 int compare_tm (struct tm *a, struct tm *b) {
609     int temp;
610     /* printf ("A is %d:%d:%d:%d:%d:%d   B is %d:%d:%d:%d:%d:%d\n",
611      *      a->tm_year+1900, a->tm_mon+1, a->tm_mday, a->tm_hour,
612      *      a->tm_min, a->tm_sec,
613      *      b->tm_year+1900, b->tm_mon+1, b->tm_mday, b->tm_hour,
614      *      b->tm_min, b->tm_sec); */
615 
616     temp = compare_int (a->tm_year, b->tm_year);
617     if (temp)
618         return temp;
619     temp = compare_int (a->tm_mon, b->tm_mon);
620     if (temp)
621         return temp;
622     temp = compare_int (a->tm_mday, b->tm_mday);
623     if (temp)
624         return temp;
625     temp = compare_int (a->tm_hour, b->tm_hour);
626     if (temp)
627         return temp;
628     temp = compare_int (a->tm_min, b->tm_min);
629     if (temp)
630         return temp;
631     return compare_int (a->tm_sec, b->tm_sec);
632 }
633 
634 /* Convert a struct tm in GMT back to a time_t.  isdst is ignored, since
635  *   it never should have been needed by mktime in the first place.
636  */
tm2gmt(struct tm * ht)637 time_t tm2gmt (struct tm *ht)
638 {
639     time_t guess, newguess, thebit;
640     int loopcounter, compare;
641     struct tm *gt;
642 
643     guess = 0;
644     loopcounter = (sizeof(time_t) * 8)-1;
645     thebit = ((time_t)1) << (loopcounter-1);
646 
647     /* For simplicity, I'm going to insist that the time_t we want is
648      *       positive.  If time_t is signed, skip the sign bit.
649      */
650     if ((signed long)thebit < (time_t)(0)) {
651         /* You can't just shift thebit right because it propagates the sign bit. */
652         loopcounter--;
653         thebit = ((time_t)1) << (loopcounter-1);
654     }
655 
656     for (; loopcounter; loopcounter--) {
657         newguess = guess | thebit;
658         gt = gmtime(&newguess);
659         if(NULL != gt)
660         {
661             compare = compare_tm (gt, ht);
662             if (compare <= 0)
663                 guess = newguess;
664         }
665         thebit >>= 1;
666     }
667 
668     return guess;
669 }
670 
yearoftimet(time_t t)671 int yearoftimet (time_t t)
672 {
673     return ((gmtime (&t))->tm_year) + 1900;
674 }
675 
676 
677 /* Calculate time_t of the epoch. */
set_epoch(IDX_entry * pIDX,int year)678 void set_epoch (IDX_entry *pIDX, int year)
679 {
680     struct tm ht;
681 
682     ht.tm_year = year - 1900;
683     ht.tm_sec = ht.tm_min = ht.tm_hour = ht.tm_mon = 0;
684     ht.tm_mday = 1;
685     pIDX->epoch = tm2gmt (&ht);
686 }
687 
688 /* Re-initialize for a different year */
happy_new_year(IDX_entry * pIDX,int new_year)689 void happy_new_year (IDX_entry *pIDX, int new_year)
690 {
691     pIDX->epoch_year = new_year;
692     figure_multipliers ( pIDX, new_year );
693     set_epoch ( pIDX, new_year );
694 }
695 
696 //      TCMgr Implementation
TCMgr()697 TCMgr::TCMgr()
698 {
699 }
700 
~TCMgr()701 TCMgr::~TCMgr()
702 {
703     PurgeData();
704 }
705 
PurgeData()706 void TCMgr::PurgeData()
707 {
708     //  Index entries are owned by the data sources
709     //  so we need to clear them from the combined list without
710     //  deleting them
711     while(m_Combined_IDX_array.GetCount()) {
712         m_Combined_IDX_array.Detach(0);
713     }
714 
715     //  Delete all the data sources
716     m_source_array.Clear();
717 }
718 
LoadDataSources(wxArrayString & sources)719 TC_Error_Code TCMgr::LoadDataSources(wxArrayString &sources)
720 {
721     PurgeData();
722 
723     //  Take a copy of dataset file name array
724     m_sourcefile_array.Clear();
725     m_sourcefile_array = sources;
726 
727     //  Arrange for the index array to begin counting at "one"
728     m_Combined_IDX_array.Add((IDX_entry *)(NULL));
729     int num_IDX = 1;
730 
731     for(unsigned int i=0 ; i < sources.GetCount() ; i++) {
732         TCDataSource *s = new TCDataSource;
733         TC_Error_Code r = s->LoadData(sources[i]);
734         if(r != TC_NO_ERROR) {
735             wxString msg;
736             msg.Printf(_T("   Error loading Tide/Currect data source %s "), sources[i].c_str());
737             if( r == TC_FILE_NOT_FOUND)
738                 msg += _T("Error Code: TC_FILE_NOT_FOUND");
739             else {
740                 wxString msg1;
741                 msg1.Printf(_T("Error code: %d"), r);
742                 msg += msg1;
743             }
744             wxLogMessage(msg);
745             delete s;
746         }
747         else {
748             m_source_array.Add(s);
749 
750             for( int k=0 ; k < s->GetMaxIndex() ; k++ ) {
751                 IDX_entry *pIDX = s->GetIndexEntry(k);
752                 pIDX->IDX_rec_num = num_IDX;
753                 num_IDX++;
754                 m_Combined_IDX_array.Add(pIDX);
755             }
756         }
757     }
758 
759     bTCMReady = true;
760 
761     if (m_Combined_IDX_array.Count() <= 1)
762         OCPNMessageBox( NULL, _("It seems you have no tide/current harmonic data installed."),
763                         _("OpenCPN Info"), wxOK | wxCENTER );
764 
765     return  TC_NO_ERROR ;
766 }
767 
GetIDX_entry(int index) const768 const IDX_entry *TCMgr::GetIDX_entry(int index) const
769 {
770     if((unsigned int)index < m_Combined_IDX_array.GetCount())
771         return &m_Combined_IDX_array[index];
772     else
773         return NULL;
774 }
775 
776 
GetTideOrCurrent(time_t t,int idx,float & tcvalue,float & dir)777 bool TCMgr::GetTideOrCurrent(time_t t, int idx, float &tcvalue, float& dir)
778 {
779     //    Return a sensible value of 0,0 by default
780     dir = 0;
781     tcvalue = 0;
782 
783     //    Load up this location data
784     IDX_entry *pIDX = &m_Combined_IDX_array[idx];    // point to the index entry
785 
786     if( !pIDX ) {
787         dir = 0;
788         tcvalue = 0;
789         return false;
790     }
791 
792     if( !pIDX->IDX_Useable ) {
793         dir = 0;
794         tcvalue = 0;
795         return(false);                                        // no error, but unuseable
796     }
797 
798     if(pIDX->pDataSource) {
799         if(pIDX->pDataSource->LoadHarmonicData(pIDX) != TC_NO_ERROR)
800             return false;
801     }
802 
803     pIDX->max_amplitude = 0.0;                // Force multiplier re-compute
804     int yott = yearoftimet( t );
805 
806     happy_new_year (pIDX, yott);              //Calculate new multipliers
807 
808     //    Finally, calculate the tide/current
809 
810     double level = time2asecondary (t + (00 * 60), pIDX);  // 300. 240
811     if(level >= 0)
812         dir = pIDX->IDX_flood_dir;
813     else
814         dir = pIDX->IDX_ebb_dir;
815 
816     tcvalue = level;
817 
818     return(true); // Got it!
819 }
820 
821 extern wxDateTime gTimeSource;
822 
GetTideOrCurrent15(time_t t_d,int idx,float & tcvalue,float & dir,bool & bnew_val)823 bool TCMgr::GetTideOrCurrent15(time_t t_d, int idx, float &tcvalue, float& dir, bool &bnew_val)
824 {
825     int ret;
826     IDX_entry *pIDX = &m_Combined_IDX_array[idx];             // point to the index entry
827 
828     if( !pIDX ) {
829         dir = 0;
830         tcvalue = 0;
831         return false;
832     }
833 
834     //    Figure out this computer timezone minute offset
835     wxDateTime this_now = gTimeSource; // wxDateTime::Now();
836     if (this_now.IsValid() == false)
837         this_now = wxDateTime::Now();
838     wxDateTime this_gmt = this_now.ToGMT();
839     wxTimeSpan diff = this_gmt.Subtract(this_now);
840     int diff_mins = diff.GetMinutes();
841 
842     int station_offset = pIDX->IDX_time_zone;
843     if(this_now.IsDST())
844         station_offset += 60;
845     int corr_mins = station_offset - diff_mins;
846 
847     wxDateTime today_00 = this_now;
848     today_00.ResetTime();
849     int t_today_00 = today_00.GetTicks();
850     int t_today_00_at_station = t_today_00 - (corr_mins * 60);
851 
852     int t_at_station = this_gmt.GetTicks() - (station_offset * 60) + (corr_mins * 60);
853 
854     int t_mins = (t_at_station - t_today_00_at_station) / 60;
855     int t_15s = t_mins / 15;
856 
857     if(pIDX->Valid15)                               // valid data available
858     {
859 
860         int tref1 = t_today_00_at_station + t_15s * 15 * 60;
861         if(tref1 == pIDX->Valid15)
862         {
863             tcvalue = pIDX->Value15;
864             dir = pIDX->Dir15;
865             bnew_val = false;
866             return pIDX->Ret15;
867         }
868         else
869         {
870             int tref = t_today_00_at_station + t_15s * 15 * 60;
871             ret = GetTideOrCurrent(tref, idx, tcvalue, dir);
872 
873             pIDX->Valid15 = tref;
874             pIDX->Value15 = tcvalue;
875             pIDX->Dir15 = dir;
876             pIDX->Ret15 = !(ret == 0);
877             bnew_val = true;
878 
879             return !(ret == 0);
880         }
881     }
882 
883     else {
884         int tref = t_today_00_at_station + t_15s * 15 * 60;
885         ret = GetTideOrCurrent(tref, idx, tcvalue, dir);
886 
887         pIDX->Valid15 = tref;
888         pIDX->Value15 = tcvalue;
889         pIDX->Dir15 = dir;
890         pIDX->Ret15 = !(ret == 0);
891         bnew_val = true;
892     }
893 
894     return !(ret == 0);
895 
896 }
897 
GetTideFlowSens(time_t t,int sch_step,int idx,float & tcvalue_now,float & tcvalue_prev,bool & w_t)898 bool TCMgr::GetTideFlowSens(time_t t, int sch_step, int idx, float &tcvalue_now, float &tcvalue_prev, bool &w_t)
899 {
900     //    Return a sensible value of 0 by default
901     tcvalue_now = 0;
902     tcvalue_prev = 0;
903     w_t = false;
904 
905 
906     //    Load up this location data
907     IDX_entry *pIDX = &m_Combined_IDX_array[idx];             // point to the index entry
908 
909     if( !pIDX )
910         return false;
911 
912     if( !pIDX->IDX_Useable )
913         return false;                                        // no error, but unuseable
914 
915     if(pIDX->pDataSource) {
916         if(pIDX->pDataSource->LoadHarmonicData(pIDX) != TC_NO_ERROR)
917             return false;
918     }
919 
920     pIDX->max_amplitude = 0.0;                // Force multiplier re-compute
921     int yott = yearoftimet( t );
922     happy_new_year (pIDX, yott);              //Force new multipliers
923 
924     //    Finally, process the tide flow sens
925 
926     tcvalue_now = time2asecondary (t , pIDX);
927     tcvalue_prev = time2asecondary (t + sch_step , pIDX);
928 
929     w_t = tcvalue_now > tcvalue_prev;           // w_t = true --> flood , w_t = false --> ebb
930 
931     return true;
932 }
933 
GetHightOrLowTide(time_t t,int sch_step_1,int sch_step_2,float tide_val,bool w_t,int idx,float & tcvalue,time_t & tctime)934 void TCMgr::GetHightOrLowTide(time_t t, int sch_step_1, int sch_step_2, float tide_val ,bool w_t , int idx, float &tcvalue, time_t &tctime)
935 {
936     //    Return a sensible value of 0,0 by default
937     tcvalue = 0;
938     tctime = t;
939 
940     //    Load up this location data
941     IDX_entry *pIDX = &m_Combined_IDX_array[idx];             // point to the index entry
942 
943     if( !pIDX )
944         return;
945 
946     if( !pIDX->IDX_Useable )
947         return;                                        // no error, but unuseable
948 
949     if(pIDX->pDataSource) {
950         if(pIDX->pDataSource->LoadHarmonicData(pIDX) != TC_NO_ERROR)
951             return;
952     }
953 
954     // Is the cache data reasonably fresh?
955     if( abs(t - pIDX->recent_highlow_calc_time) < 60){
956         if(w_t){
957             tcvalue = pIDX->recent_high_level;
958             tctime = pIDX->recent_high_time;
959         }else{
960             tcvalue = pIDX->recent_low_level;
961             tctime = pIDX->recent_low_time;
962         }
963         return;
964     }
965 
966 
967     pIDX->max_amplitude = 0.0;                // Force multiplier re-compute
968     int yott = yearoftimet( t );
969     happy_new_year (pIDX, yott);
970 
971     // Finally, calculate the Hight and low tides
972     double newval = tide_val;
973     double oldval = ( w_t ) ? newval - 1: newval + 1 ;
974     int j = 0 ;
975     int k = 0 ;
976     int ttt = 0 ;
977     while ( (newval > oldval) == w_t )                  //searching each ten minute
978     {
979         j++;
980         oldval = newval;
981         ttt = t + ( sch_step_1 * j );
982         newval = time2asecondary (ttt, pIDX);
983     }
984     oldval = ( w_t ) ? newval - 1: newval + 1 ;
985     while ( (newval > oldval) == w_t )                  // searching back each minute
986     {
987         oldval = newval ;
988         k++;
989         ttt = t +  ( sch_step_1 * j ) - ( sch_step_2 * k ) ;
990         newval = time2asecondary (ttt, pIDX);
991     }
992     tcvalue = newval;
993     tctime = ttt + sch_step_2 ;
994 
995     // Cache the data
996     pIDX->recent_highlow_calc_time = t;
997     if(w_t){
998         pIDX->recent_high_level = newval;
999         pIDX->recent_high_time = tctime;
1000     }
1001     else{
1002         pIDX->recent_low_level = newval;
1003         pIDX->recent_low_time = tctime;
1004     }
1005 
1006 
1007 }
1008 
GetStationTimeOffset(IDX_entry * pIDX)1009 int TCMgr::GetStationTimeOffset(IDX_entry *pIDX)
1010 {
1011     return pIDX->IDX_time_zone;
1012 }
1013 
GetStationLat(IDX_entry * pIDX)1014 double  TCMgr::GetStationLat(IDX_entry *pIDX)
1015 {
1016     return pIDX->IDX_lat;
1017 }
1018 
GetStationLon(IDX_entry * pIDX)1019 double  TCMgr::GetStationLon(IDX_entry *pIDX)
1020 {
1021     return pIDX->IDX_lon;
1022 }
1023 
GetNextBigEvent(time_t * tm,int idx)1024 int TCMgr::GetNextBigEvent(time_t *tm, int idx)
1025 {
1026     float tcvalue[1];
1027     float dir;
1028     bool ret;
1029     double p, q;
1030     int flags = 0, slope = 0;
1031     ret = GetTideOrCurrent(*tm, idx, tcvalue[0],  dir);
1032     p = tcvalue[0];
1033     *tm += 60;
1034     ret = GetTideOrCurrent(*tm, idx, tcvalue[0],  dir);
1035     q = tcvalue[0];
1036     *tm += 60;
1037     if (p < q)
1038         slope = 1;
1039     while (1) {
1040         if ((slope == 1 && q < p) || (slope == 0 && p < q)) {
1041             /* Tide event */
1042             flags |= (1 << slope);
1043         }
1044         if (flags) {
1045             *tm -= 60;
1046             if (flags < 4)
1047                 *tm -= 60;
1048             return flags;
1049         }
1050         p = q;
1051         ret = GetTideOrCurrent(*tm, idx, tcvalue[0],  dir);
1052         q = tcvalue[0];
1053         *tm += 60;
1054     }
1055     return 0;
1056 }
1057 
GetStationsForLL(double xlat,double xlon) const1058 std::map<double, const IDX_entry*> TCMgr::GetStationsForLL(double xlat, double xlon) const
1059 {
1060     std::map<double, const IDX_entry*> x;
1061     const IDX_entry *lpIDX;
1062 
1063     for ( int j=1 ; j<Get_max_IDX() +1 ; j++ ) {
1064         lpIDX = GetIDX_entry ( j );
1065         char type = lpIDX->IDX_type;
1066         wxString locnx ( lpIDX->IDX_station_name, wxConvUTF8 );
1067 
1068         if ( type == 't' || type == 'T' ) {
1069             double brg, dist;
1070             DistanceBearingMercator(xlat, xlon, lpIDX->IDX_lat, lpIDX->IDX_lon, &brg, &dist);
1071             x.emplace(std::make_pair(dist, lpIDX));
1072         }
1073     }
1074 
1075     return x;
1076 }
1077 
GetStationIDXbyName(const wxString & prefix,double xlat,double xlon) const1078 int TCMgr::GetStationIDXbyName(const wxString & prefix, double xlat, double xlon) const
1079 {
1080     const IDX_entry *lpIDX;
1081     int jx = 0;
1082     wxString locn;
1083     double distx = 100000.;
1084 
1085     int jmax = Get_max_IDX();
1086 
1087     for ( int j=1 ; j<Get_max_IDX() +1 ; j++ ) {
1088         lpIDX = GetIDX_entry ( j );
1089         char type = lpIDX->IDX_type;             // Entry "TCtcIUu" identifier
1090         wxString locnx ( lpIDX->IDX_station_name, wxConvUTF8 );
1091 
1092         if ( (( type == 't' ) ||  ( type == 'T' ) )   // only Tides
1093                 && (locnx.StartsWith(prefix))) {
1094             double brg, dist;
1095             DistanceBearingMercator(xlat, xlon, lpIDX->IDX_lat, lpIDX->IDX_lon, &brg, &dist);
1096             if (dist < distx) {
1097                 distx = dist;
1098                 jx = j;
1099             }
1100         }
1101     } // end for loop
1102     //} // end if @~~ found in WP
1103     return(jx);
1104 }
1105 
1106 
GetStationIDXbyNameType(const wxString & prefix,double xlat,double xlon,char type) const1107 int TCMgr::GetStationIDXbyNameType(const wxString & prefix, double xlat, double xlon, char type) const
1108 {
1109     const IDX_entry *lpIDX;
1110     int jx = 0;
1111     wxString locn;
1112     double distx = 100000.;
1113 
1114     // if (prp->m_MarkName.Find(_T("@~~")) != wxNOT_FOUND) {
1115     //tide_form = prp->m_MarkName.Mid(prp->m_MarkName.Find(_T("@~~"))+3);
1116     int jmax = Get_max_IDX();
1117 
1118     for ( int j=1 ; j<Get_max_IDX() +1 ; j++ ) {
1119         lpIDX = GetIDX_entry ( j );
1120         char typep = lpIDX->IDX_type;             // Entry "TCtcIUu" identifier
1121         wxString locnx ( lpIDX->IDX_station_name, wxConvUTF8 );
1122 
1123         if ( ( type == typep ) && (locnx.StartsWith(prefix))) {
1124             double brg, dist;
1125             DistanceBearingMercator(xlat, xlon, lpIDX->IDX_lat, lpIDX->IDX_lon, &brg, &dist);
1126             if (dist < distx) {
1127                 distx = dist;
1128                 jx = j;
1129             }
1130         }
1131     } // end for loop
1132     return(jx);
1133 }
1134 
1135 
1136 /* $Id: tide_db_default.h 1092 2006-11-16 03:02:42Z flaterco $ */
1137 
1138 //#include "tcd.h"
1139 
1140 
1141 
1142 /*****************************************************************************
1143  *
1144  *                            DISTRIBUTION STATEMENT
1145  *
1146  *    This source file is unclassified, distribution unlimited, public
1147  *    domain.  It is distributed in the hope that it will be useful, but
1148  *    WITHOUT ANY WARRANTY; without even the implied warranty of
1149  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1150  *
1151  ******************************************************************************/
1152 
1153 
1154 
1155 #define DEFAULT_HEADER_SIZE                         4096
1156 #define DEFAULT_NUMBER_OF_RECORDS                   0
1157 #define DEFAULT_LEVEL_UNIT_TYPES                    5
1158 #define DEFAULT_DIR_UNIT_TYPES                      3
1159 #define DEFAULT_RESTRICTION_TYPES                   2
1160 #define DEFAULT_RESTRICTION_BITS                    4
1161 #define DEFAULT_TZFILES                             406
1162 #define DEFAULT_TZFILE_BITS                         10
1163 #define DEFAULT_COUNTRIES                           240
1164 #define DEFAULT_COUNTRY_BITS                        9
1165 #define DEFAULT_DATUM_TYPES                         61
1166 #define DEFAULT_DATUM_BITS                          7
1167 #define DEFAULT_LEGALESES                           1
1168 #define DEFAULT_LEGALESE_BITS                       4
1169 #define DEFAULT_SPEED_SCALE                         10000000
1170 #define DEFAULT_EQUILIBRIUM_SCALE                   100
1171 #define DEFAULT_NODE_SCALE                          10000
1172 #define DEFAULT_AMPLITUDE_BITS                      19
1173 #define DEFAULT_AMPLITUDE_SCALE                     10000
1174 #define DEFAULT_EPOCH_BITS                          16
1175 #define DEFAULT_EPOCH_SCALE                         100
1176 #define DEFAULT_RECORD_TYPE_BITS                    4
1177 #define DEFAULT_LATITUDE_BITS                       25
1178 #define DEFAULT_LATITUDE_SCALE                      100000
1179 #define DEFAULT_LONGITUDE_BITS                      26
1180 #define DEFAULT_LONGITUDE_SCALE                     100000
1181 #define DEFAULT_RECORD_SIZE_BITS                    16
1182 #define DEFAULT_STATION_BITS                        18
1183 #define DEFAULT_DATUM_OFFSET_BITS                   28
1184 #define DEFAULT_DATUM_OFFSET_SCALE                  10000
1185 #define DEFAULT_DATE_BITS                           27
1186 #define DEFAULT_MONTHS_ON_STATION_BITS              10
1187 #define DEFAULT_CONFIDENCE_VALUE_BITS               4
1188 #define DEFAULT_NUMBER_OF_CONSTITUENTS_BITS         8
1189 #define DEFAULT_TIME_BITS                           13
1190 #define DEFAULT_LEVEL_ADD_BITS                      17
1191 #define DEFAULT_LEVEL_ADD_SCALE                     1000
1192 #define DEFAULT_LEVEL_MULTIPLY_BITS                 16
1193 #define DEFAULT_LEVEL_MULTIPLY_SCALE                1000
1194 #define DEFAULT_DIRECTION_BITS                      9
1195 #define DEFAULT_CONSTITUENT_SIZE                    10
1196 #define DEFAULT_LEVEL_UNIT_SIZE                     15
1197 #define DEFAULT_DIR_UNIT_SIZE                       15
1198 #define DEFAULT_RESTRICTION_SIZE                    30
1199 #define DEFAULT_DATUM_SIZE                          70
1200 #define DEFAULT_LEGALESE_SIZE                       70
1201 #define DEFAULT_TZFILE_SIZE                         30
1202 #define DEFAULT_COUNTRY_SIZE                        50
1203 
1204 
1205 /*  Stuff for inferring constituents (NAVO short duration tide stations).  */
1206 
1207 #define INFERRED_SEMI_DIURNAL_COUNT                 10
1208 #define INFERRED_DIURNAL_COUNT                      10
1209 
1210 #ifdef __MSVC__
1211 #pragma warning (disable : 4305)                // conversion loss, double to float
1212 #endif
1213 
1214 const NV_CHAR *inferred_semi_diurnal[INFERRED_SEMI_DIURNAL_COUNT] = {
1215     "N2", "NU2", "MU2", "2N2", "LDA2", "T2", "R2", "L2", "K2", "KJ2"};
1216     const NV_CHAR *inferred_diurnal[INFERRED_DIURNAL_COUNT] = {
1217         "OO1", "M1", "J1", "RHO1", "Q1", "2Q1", "P1", "PI1", "PHI1", "PSI1"};
1218         NV_FLOAT32 semi_diurnal_coeff[INFERRED_SEMI_DIURNAL_COUNT] = {
1219             .1759, .0341, .0219, .0235, .0066, .0248, .0035, .0251, .1151, .0064};
1220             NV_FLOAT32 diurnal_coeff[INFERRED_DIURNAL_COUNT] = {
1221                 .0163, .0209, .0297, .0142, .0730, .0097, .1755, .0103, .0076, .0042};
1222 
1223                 /*  These represent M2 and O1.  */
1224 
1225                 NV_FLOAT32 coeff[2] = {.9085, .3771};
1226 
1227                 /* The following lookup tables are only used for initialization
1228                  *   purposes and in the pull-down menus in TideEditor.  It should be
1229                  *   possible to change them without breaking existing TCD files.  TCD
1230                  *   files embed their own lookup tables.
1231                  */
1232 
1233 
1234                 /*  Level unit names  */
1235 
1236                 NV_CHAR level_unit[DEFAULT_LEVEL_UNIT_TYPES][DEFAULT_LEVEL_UNIT_SIZE] = {
1237                     "Unknown", "feet", "meters", "knots", "knots^2"};
1238 
1239 
1240                     /*  Direction unit names  */
1241 
1242                     NV_CHAR dir_unit[DEFAULT_DIR_UNIT_TYPES][DEFAULT_DIR_UNIT_SIZE] = {
1243                         "Unknown", "degrees true", "degrees"};
1244 
1245 
1246                         /*  Restriction types  */
1247 
1248                         NV_CHAR restriction[DEFAULT_RESTRICTION_TYPES][DEFAULT_RESTRICTION_SIZE] = {
1249                             "Public Domain", "DoD/DoD Contractors Only"};
1250 
1251 
1252                             /*  Legaleses  */
1253 
1254                             NV_CHAR legalese[DEFAULT_LEGALESES][DEFAULT_LEGALESE_SIZE] = {
1255                                 "NULL"};
1256 
1257 
1258                                 /*  # Datum names  */
1259 
1260                                 NV_CHAR datum[DEFAULT_DATUM_TYPES][DEFAULT_DATUM_SIZE] = {
1261                                     "Unknown", "Mean Sea Level", "Mean Low Water", "Mean Lower Low Water",
1262                                     "Mean High Water", "Mean Higher High Water", "Mean Lower High Water",
1263                                     "Mean Higher Low Water", "Mean Low Water Springs",
1264                                     "Mean Lower Low Water Springs", "Mean Low Water Neaps",
1265                                     "Mean High Water Neaps", "Mean High Water Springs",
1266                                     "Mean Higher High Water Springs", "Indian Spring Low Water",
1267                                     "Equatorial Spring Low Water", "Lowest Normal Low Water", "Lowest Low Water",
1268                                     "Lowest Possible Low Water", "Lowest Astronomical Tide",
1269                                     "International Great Lakes Datum(1955)", "Lower Low Water, Large Tide",
1270                                     "Lowest Normal Tide", "Higher High Water, Large Tide", "Mean Water Level",
1271                                     "Higher High Water, Mean Tide", "Lower Low Water, Mean Tide",
1272                                     "Mean Tide Level", "World Geodetic System (1984)",
1273                                     "National Geodetic Vertical Datum", "Gulf Coast Low Water Datum",
1274                                     "Approximate Level of Mean Sea Level",
1275                                     "Approximate Level of Mean Low Water",
1276                                     "Approximate Level of Mean Lower Low Water",
1277                                     "Approximate Level of Mean High Water",
1278                                     "Approximate Level of Mean Higher High Water",
1279                                     "Approximate Level of Mean Lower High Water",
1280                                     "Approximate Level of Mean Higher Low Water",
1281                                     "Approximate Level of Mean Low Water Springs",
1282                                     "Approximate Level of Mean Lower Low Water Springs",
1283                                     "Approximate Level of Mean Low Water Neaps",
1284                                     "Approximate Level of Mean High Water Neaps",
1285                                     "Approximate Level of Mean High Water Springs",
1286                                     "Approximate Level of Mean Higher High Water Springs",
1287                                     "Approximate Level of Indian Spring Low Water",
1288                                     "Approximate Level of Equatorial Spring Low Water",
1289                                     "Approximate Level of Lowest Normal Low Water",
1290                                     "Approximate Level of Lowest Low Water",
1291                                     "Approximate Level of Lowest Possible Low Water",
1292                                     "Approximate Level of Lowest Astronomical Tide",
1293                                     "Approximate Level of International Great Lakes Datum (1955)",
1294                                     "Approximate Level of Lower Low Water, Large Tide",
1295                                     "Approximate Level of Lowest Normal Tide",
1296                                     "Approximate Level of Higher High Water, Large Tide",
1297                                     "Approximate Level of Mean Water Level",
1298                                     "Approximate Level of Higher High Water, Mean Tide",
1299                                     "Approximate Level of Lower Low Water, Mean Tide",
1300                                     "Approximate Level of Mean Tide Level",
1301                                     "Approximate Level of World Geodetic System (1984)",
1302                                     "Approximate Level of National Geodetic Vertical Datum",
1303                                     "Approximate Level of Gulf Coast Low Water Datum"};
1304 
1305 
1306                                     /*  # Country names from ISO 3166-1:1999 2-character country code list  */
1307 
1308                                     NV_CHAR country[DEFAULT_COUNTRIES][DEFAULT_COUNTRY_SIZE] = {"Unknown",
1309                                     "Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Anguilla",
1310                                     "Antarctica", "Antigua & Barbuda", "Argentina", "Armenia", "Aruba",
1311                                     "Australia", "Austria", "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh",
1312                                     "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bermuda", "Bhutan",
1313                                     "Bolivia", "Bosnia & Herzegovina", "Botswana", "Bouvet Island", "Brazil",
1314                                     "Britain (UK)", "British Indian Ocean Territory", "Brunei", "Bulgaria",
1315                                     "Burkina Faso", "Burundi", "Cambodia", "Cameroon", "Canada", "Cape Verde",
1316                                     "Cayman Islands", "Central African Rep.", "Chad", "Chile", "China",
1317                                     "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros",
1318                                     "Congo (Dem. Rep.)", "Congo (Rep.)", "Cook Islands", "Costa Rica",
1319                                     "Cote d'Ivoire", "Croatia", "Cuba", "Cyprus", "Czech Republic", "Denmark",
1320                                     "Djibouti", "Dominica", "Dominican Republic", "East Timor", "Ecuador",
1321                                     "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia",
1322                                     "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
1323                                     "France", "French Guiana", "French Polynesia",
1324                                     "French Southern & Antarctic Lands", "Gabon", "Gambia", "Georgia", "Germany",
1325                                     "Ghana", "Gibraltar", "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam",
1326                                     "Guatemala", "Guinea", "Guinea-Bissau", "Guyana", "Haiti",
1327                                     "Heard Island & McDonald Islands", "Honduras", "Hong Kong", "Hungary",
1328                                     "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel",
1329                                     "Italy", "Jamaica", "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati",
1330                                     "Korea (North)", "Korea (South)", "Kuwait", "Kyrgyzstan", "Laos", "Latvia",
1331                                     "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania",
1332                                     "Luxembourg", "Macau", "Macedonia", "Madagascar", "Malawi", "Malaysia",
1333                                     "Maldives", "Mali", "Malta", "Marshall Islands", "Martinique", "Mauritania",
1334                                     "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova", "Monaco",
1335                                     "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar (Burma)",
1336                                     "Namibia", "Nauru", "Nepal", "Netherlands", "Netherlands Antilles",
1337                                     "New Caledonia", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Niue",
1338                                     "Norfolk Island", "Northern Mariana Islands", "Norway", "Oman", "Pakistan",
1339                                     "Palau", "Palestine", "Panama", "Papua New Guinea", "Paraguay", "Peru",
1340                                     "Philippines", "Pitcairn", "Poland", "Portugal", "Puerto Rico", "Qatar",
1341                                     "Reunion", "Romania", "Russia", "Rwanda", "Samoa (American)",
1342                                     "Samoa (Western)", "San Marino", "Sao Tome & Principe", "Saudi Arabia",
1343                                     "Senegal", "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia",
1344                                     "Solomon Islands", "Somalia", "South Africa",
1345                                     "South Georgia & the South Sandwich Islands", "Spain", "Sri Lanka",
1346                                     "St Helena", "St Kitts & Nevis", "St Lucia", "St Pierre & Miquelon",
1347                                     "St Vincent", "Sudan", "Suriname", "Svalbard & Jan Mayen", "Swaziland",
1348                                     "Sweden", "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania",
1349                                     "Thailand", "Togo", "Tokelau", "Tonga", "Trinidad & Tobago", "Tunisia",
1350                                     "Turkey", "Turkmenistan", "Turks & Caicos Is", "Tuvalu", "Uganda", "Ukraine",
1351                                     "United Arab Emirates", "United States", "Uruguay",
1352                                     "US minor outlying islands", "Uzbekistan", "Vanuatu", "Vatican City",
1353                                     "Venezuela", "Vietnam", "Virgin Islands (UK)", "Virgin Islands (US)",
1354                                     "Wallis & Futuna", "Western Sahara", "Yemen", "Yugoslavia", "Zambia",
1355                                     "Zimbabwe"};
1356 
1357 
1358                                     /*  # Time zones extracted from tzdata2002? .  */
1359 
1360                                     NV_CHAR tzfile[DEFAULT_TZFILES][DEFAULT_TZFILE_SIZE] = {"Unknown",
1361                                     ":Africa/Abidjan", ":Africa/Accra", ":Africa/Addis_Ababa",
1362                                     ":Africa/Algiers", ":Africa/Asmera", ":Africa/Bamako",
1363                                     ":Africa/Bangui", ":Africa/Banjul", ":Africa/Bissau",
1364                                     ":Africa/Blantyre", ":Africa/Brazzaville", ":Africa/Bujumbura",
1365                                     ":Africa/Cairo", ":Africa/Casablanca", ":Africa/Ceuta",
1366                                     ":Africa/Conakry", ":Africa/Dakar", ":Africa/Dar_es_Salaam",
1367                                     ":Africa/Djibouti", ":Africa/Douala", ":Africa/El_Aaiun",
1368                                     ":Africa/Freetown", ":Africa/Gaborone", ":Africa/Harare",
1369                                     ":Africa/Johannesburg", ":Africa/Kampala", ":Africa/Khartoum",
1370                                     ":Africa/Kigali", ":Africa/Kinshasa", ":Africa/Lagos",
1371                                     ":Africa/Libreville", ":Africa/Lome", ":Africa/Luanda",
1372                                     ":Africa/Lubumbashi", ":Africa/Lusaka", ":Africa/Malabo",
1373                                     ":Africa/Maputo", ":Africa/Maseru", ":Africa/Mbabane",
1374                                     ":Africa/Mogadishu", ":Africa/Monrovia", ":Africa/Nairobi",
1375                                     ":Africa/Ndjamena", ":Africa/Niamey", ":Africa/Nouakchott",
1376                                     ":Africa/Ouagadougou", ":Africa/Porto-Novo", ":Africa/Sao_Tome",
1377                                     ":Africa/Timbuktu", ":Africa/Tripoli", ":Africa/Tunis",
1378                                     ":Africa/Windhoek", ":America/Adak", ":America/Anchorage",
1379                                     ":America/Anguilla", ":America/Antigua", ":America/Araguaina",
1380                                     ":America/Aruba", ":America/Asuncion", ":America/Atka",
1381                                     ":America/Barbados", ":America/Belem", ":America/Belize",
1382                                     ":America/Boa_Vista", ":America/Bogota", ":America/Boise",
1383                                     ":America/Buenos_Aires", ":America/Cambridge_Bay",
1384                                     ":America/Cancun", ":America/Caracas", ":America/Catamarca",
1385                                     ":America/Cayenne", ":America/Cayman", ":America/Chicago",
1386                                     ":America/Chihuahua", ":America/Cordoba", ":America/Costa_Rica",
1387                                     ":America/Cuiaba", ":America/Curacao", ":America/Danmarkshavn",
1388                                     ":America/Dawson", ":America/Dawson_Creek", ":America/Denver",
1389                                     ":America/Detroit", ":America/Dominica", ":America/Edmonton",
1390                                     ":America/Eirunepe", ":America/El_Salvador", ":America/Ensenada",
1391                                     ":America/Fortaleza", ":America/Glace_Bay", ":America/Godthab",
1392                                     ":America/Goose_Bay", ":America/Grand_Turk", ":America/Grenada",
1393                                     ":America/Guadeloupe", ":America/Guatemala", ":America/Guayaquil",
1394                                     ":America/Guyana", ":America/Halifax", ":America/Havana",
1395                                     ":America/Hermosillo", ":America/Indiana/Knox",
1396                                     ":America/Indiana/Marengo", ":America/Indianapolis",
1397                                     ":America/Indiana/Vevay", ":America/Inuvik", ":America/Iqaluit",
1398                                     ":America/Jamaica", ":America/Jujuy", ":America/Juneau",
1399                                     ":America/Kentucky/Monticello", ":America/La_Paz", ":America/Lima",
1400                                     ":America/Los_Angeles", ":America/Louisville", ":America/Maceio",
1401                                     ":America/Managua", ":America/Manaus", ":America/Martinique",
1402                                     ":America/Mazatlan", ":America/Mendoza", ":America/Menominee",
1403                                     ":America/Merida", ":America/Mexico_City", ":America/Miquelon",
1404                                     ":America/Monterrey", ":America/Montevideo", ":America/Montreal",
1405                                     ":America/Montserrat", ":America/Nassau", ":America/New_York",
1406                                     ":America/Nipigon", ":America/Nome", ":America/Noronha",
1407                                     ":America/North_Dakota/Center", ":America/Panama",
1408                                     ":America/Pangnirtung", ":America/Paramaribo", ":America/Phoenix",
1409                                     ":America/Port-au-Prince", ":America/Port_of_Spain",
1410                                     ":America/Porto_Velho", ":America/Puerto_Rico",
1411                                     ":America/Rainy_River", ":America/Rankin_Inlet", ":America/Recife",
1412                                     ":America/Regina", ":America/Rio_Branco", ":America/Santiago",
1413                                     ":America/Santo_Domingo", ":America/Sao_Paulo",
1414                                     ":America/Scoresbysund", ":America/Shiprock", ":America/St_Johns",
1415                                     ":America/St_Kitts", ":America/St_Lucia", ":America/St_Thomas",
1416                                     ":America/St_Vincent", ":America/Swift_Current",
1417                                     ":America/Tegucigalpa", ":America/Thule", ":America/Thunder_Bay",
1418                                     ":America/Tijuana", ":America/Tortola", ":America/Vancouver",
1419                                     ":America/Whitehorse", ":America/Winnipeg", ":America/Yakutat",
1420                                     ":America/Yellowknife", ":Antarctica/Casey", ":Antarctica/Davis",
1421                                     ":Antarctica/DumontDUrville", ":Antarctica/Mawson",
1422                                     ":Antarctica/McMurdo", ":Antarctica/Palmer",
1423                                     ":Antarctica/South_Pole", ":Antarctica/Syowa", ":Antarctica/Vostok",
1424                                     ":Arctic/Longyearbyen", ":Asia/Aden", ":Asia/Almaty", ":Asia/Amman",
1425                                     ":Asia/Anadyr", ":Asia/Aqtau", ":Asia/Aqtobe", ":Asia/Ashgabat",
1426                                     ":Asia/Baghdad", ":Asia/Bahrain", ":Asia/Baku", ":Asia/Bangkok",
1427                                     ":Asia/Beirut", ":Asia/Bishkek", ":Asia/Brunei", ":Asia/Calcutta",
1428                                     ":Asia/Choibalsan", ":Asia/Chongqing", ":Asia/Colombo",
1429                                     ":Asia/Damascus", ":Asia/Dhaka", ":Asia/Dili", ":Asia/Dubai",
1430                                     ":Asia/Dushanbe", ":Asia/Gaza", ":Asia/Harbin", ":Asia/Hong_Kong",
1431                                     ":Asia/Hovd", ":Asia/Irkutsk", ":Asia/Jakarta", ":Asia/Jayapura",
1432                                     ":Asia/Jerusalem", ":Asia/Kabul", ":Asia/Kamchatka",
1433                                     ":Asia/Karachi", ":Asia/Kashgar", ":Asia/Katmandu",
1434                                     ":Asia/Krasnoyarsk", ":Asia/Kuala_Lumpur", ":Asia/Kuching",
1435                                     ":Asia/Kuwait", ":Asia/Macau", ":Asia/Magadan", ":Asia/Makassar",
1436                                     ":Asia/Manila", ":Asia/Muscat", ":Asia/Nicosia",
1437                                     ":Asia/Novosibirsk", ":Asia/Omsk", ":Asia/Oral", ":Asia/Phnom_Penh",
1438                                     ":Asia/Pontianak", ":Asia/Pyongyang", ":Asia/Qatar",
1439                                     ":Asia/Qyzylorda", ":Asia/Rangoon", ":Asia/Riyadh", ":Asia/Saigon",
1440                                     ":Asia/Sakhalin", ":Asia/Samarkand", ":Asia/Seoul",
1441                                     ":Asia/Shanghai", ":Asia/Singapore", ":Asia/Taipei",
1442                                     ":Asia/Tashkent", ":Asia/Tbilisi", ":Asia/Tehran", ":Asia/Thimphu",
1443                                     ":Asia/Tokyo", ":Asia/Ulaanbaatar", ":Asia/Urumqi",
1444                                     ":Asia/Vientiane", ":Asia/Vladivostok", ":Asia/Yakutsk",
1445                                     ":Asia/Yekaterinburg", ":Asia/Yerevan", ":Atlantic/Azores",
1446                                     ":Atlantic/Bermuda", ":Atlantic/Canary", ":Atlantic/Cape_Verde",
1447                                     ":Atlantic/Faeroe", ":Atlantic/Jan_Mayen", ":Atlantic/Madeira",
1448                                     ":Atlantic/Reykjavik", ":Atlantic/South_Georgia",
1449                                     ":Atlantic/Stanley", ":Atlantic/St_Helena", ":Australia/Adelaide",
1450                                     ":Australia/Brisbane", ":Australia/Broken_Hill",
1451                                     ":Australia/Darwin", ":Australia/Hobart", ":Australia/Lindeman",
1452                                     ":Australia/Lord_Howe", ":Australia/Melbourne", ":Australia/Perth",
1453                                     ":Australia/Sydney", ":Etc/GMT", ":Etc/GMT-1", ":Etc/GMT+1",
1454                                     ":Etc/GMT-10", ":Etc/GMT+10", ":Etc/GMT-11", ":Etc/GMT+11",
1455                                     ":Etc/GMT-12", ":Etc/GMT+12", ":Etc/GMT-13", ":Etc/GMT-14",
1456                                     ":Etc/GMT-2", ":Etc/GMT+2", ":Etc/GMT-3", ":Etc/GMT+3",
1457                                     ":Etc/GMT-4", ":Etc/GMT+4", ":Etc/GMT-5", ":Etc/GMT+5",
1458                                     ":Etc/GMT-6", ":Etc/GMT+6", ":Etc/GMT-7", ":Etc/GMT+7",
1459                                     ":Etc/GMT-8", ":Etc/GMT+8", ":Etc/GMT-9", ":Etc/GMT+9", ":Etc/UCT",
1460                                     ":Etc/UTC", ":Europe/Amsterdam", ":Europe/Andorra",
1461                                     ":Europe/Athens", ":Europe/Belfast", ":Europe/Belgrade",
1462                                     ":Europe/Berlin", ":Europe/Bratislava", ":Europe/Brussels",
1463                                     ":Europe/Bucharest", ":Europe/Budapest", ":Europe/Chisinau",
1464                                     ":Europe/Copenhagen", ":Europe/Dublin", ":Europe/Gibraltar",
1465                                     ":Europe/Helsinki", ":Europe/Istanbul", ":Europe/Kaliningrad",
1466                                     ":Europe/Kiev", ":Europe/Lisbon", ":Europe/Ljubljana",
1467                                     ":Europe/London", ":Europe/Luxembourg", ":Europe/Madrid",
1468                                     ":Europe/Malta", ":Europe/Minsk", ":Europe/Monaco",
1469                                     ":Europe/Moscow", ":Europe/Oslo", ":Europe/Paris", ":Europe/Prague",
1470                                     ":Europe/Riga", ":Europe/Rome", ":Europe/Samara",
1471                                     ":Europe/San_Marino", ":Europe/Sarajevo", ":Europe/Simferopol",
1472                                     ":Europe/Skopje", ":Europe/Sofia", ":Europe/Stockholm",
1473                                     ":Europe/Tallinn", ":Europe/Tirane", ":Europe/Uzhgorod",
1474                                     ":Europe/Vaduz", ":Europe/Vatican", ":Europe/Vienna",
1475                                     ":Europe/Vilnius", ":Europe/Warsaw", ":Europe/Zagreb",
1476                                     ":Europe/Zaporozhye", ":Europe/Zurich", ":Indian/Antananarivo",
1477                                     ":Indian/Chagos", ":Indian/Christmas", ":Indian/Cocos",
1478                                     ":Indian/Comoro", ":Indian/Kerguelen", ":Indian/Mahe",
1479                                     ":Indian/Maldives", ":Indian/Mauritius", ":Indian/Mayotte",
1480                                     ":Indian/Reunion", ":Pacific/Apia", ":Pacific/Auckland",
1481                                     ":Pacific/Chatham", ":Pacific/Easter", ":Pacific/Efate",
1482                                     ":Pacific/Enderbury", ":Pacific/Fakaofo", ":Pacific/Fiji",
1483                                     ":Pacific/Funafuti", ":Pacific/Galapagos", ":Pacific/Gambier",
1484                                     ":Pacific/Guadalcanal", ":Pacific/Guam", ":Pacific/Honolulu",
1485                                     ":Pacific/Johnston", ":Pacific/Kiritimati", ":Pacific/Kosrae",
1486                                     ":Pacific/Kwajalein", ":Pacific/Majuro", ":Pacific/Marquesas",
1487                                     ":Pacific/Midway", ":Pacific/Nauru", ":Pacific/Niue",
1488                                     ":Pacific/Norfolk", ":Pacific/Noumea", ":Pacific/Pago_Pago",
1489                                     ":Pacific/Palau", ":Pacific/Pitcairn", ":Pacific/Ponape",
1490                                     ":Pacific/Port_Moresby", ":Pacific/Rarotonga", ":Pacific/Saipan",
1491                                     ":Pacific/Tahiti", ":Pacific/Tarawa", ":Pacific/Tongatapu",
1492                                     ":Pacific/Truk", ":Pacific/Wake", ":Pacific/Wallis",
1493                                     ":Pacific/Yap"};
1494 
1495 
1496 
1497 /* $Id: tide_db.c 3744 2010-08-17 22:34:46Z flaterco $ */
1498 
1499 //#include "tcd.h"
1500 //#include "tide_db_header.h"
1501 //#include "tide_db_default.h"
1502 
1503 /* This should be done with stdbool.h, but VC doesn't have it. */
1504 /* Using crappy old int, must be careful not to 'require' a 64-bit value. */
1505 #ifndef require
1506 #define require(expr) {       \
1507   int require_expr;           \
1508   require_expr = (int)(expr); \
1509   assert (require_expr);      \
1510 }
1511 #endif
1512 
1513 #include <stdio.h>
1514 #include <stdlib.h>
1515 #include <string.h>
1516 #include <errno.h>
1517 #include <time.h>
1518 #include <math.h>
1519 #include <ctype.h>
1520 #include <assert.h>
1521 
1522 #ifdef HAVE_UNISTD_H
1523 #include <unistd.h>
1524 #endif
1525 
1526 #ifdef HAVE_IO_H
1527 #include <io.h>
1528 #endif
1529 
1530 
1531 /****************************************************************************
1532 
1533                             DISTRIBUTION STATEMENT
1534 
1535     This source file is unclassified, distribution unlimited, public
1536     domain.  It is distributed in the hope that it will be useful, but
1537     WITHOUT ANY WARRANTY; without even the implied warranty of
1538     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1539 
1540 *****************************************************************************/
1541 
1542 
1543 
1544 /* Some of the following commentary is out of date.  See the new
1545    documentation in libtcd.html. */
1546 
1547 /****************************************************************************
1548 
1549     Tide Constituent Database API
1550 
1551 
1552     Author  : Jan C. Depner (depnerj@navo.navy.mil)
1553 
1554     Date    : 08/01/02
1555               (First day of Micro$oft's "Licensing 6" policy - P.T. Barnum was
1556               right!!!)
1557 
1558     Purpose : To replace the ASCII/XML formatted harmonic constituent data
1559               files, used in Dave Flater's (http://www.flaterco.com/xtide/)
1560               exceptionally fine open-source XTide program, with a fast,
1561               efficient binary format.  In addition, we wanted to replace the
1562               Naval Oceanographic Office's (http://www.navo.navy.mil)
1563               antiquated ASCII format harmonic constituent data file due to
1564               problems with configuration management of the file.  The
1565               resulting database will become a Navy OAML (Oceanographic and
1566               Atmospheric Master Library) standard harmonic tide constituent
1567               database.
1568 
1569     Design  : The following describes the database file and some of the
1570               rationale behind the design.
1571 
1572     First question - Why didn't I use PostgreSQL or MySQL?  Mostly
1573     portability.  What?  PostgreSQL runs on everything!  Yes, but it doesn't
1574     come installed on everything.  This would have meant that the poor,
1575     benighted Micro$oft borgs would have had to actually load a software
1576     package.  In addition, the present harmonics/offset files only contain
1577     a total of 6,409 stations.  It hardly seemed worth the effort (or overhead)
1578     of a fullblown RDBMS to handle this.  Second question - Why binary and not
1579     ASCII or XML?  This actually gets into philosophy.  At NAVO we have used an
1580     ASCII harmonic constituent file for years (we were founded in 1830 and I
1581     think that that's when they designed the file).  We have about fifty
1582     million copies floating around and each one is slightly different.  Why?
1583     Because they're ASCII and everyone thinks they know what they're doing so
1584     they tend to modify the file.  Same problem with XML, it's still ASCII.
1585     We wanted a file that people weren't going to mess with and that we could
1586     version control.  We also wanted a file that was small and fast.  This is
1587     very difficult to do with ASCII.  The big slowdown with the old format
1588     was I/O and parsing.  Third question - will it run on any OS?  Hopefully,
1589     yes.  After twenty-five years of working with low bidder systems I've
1590     worked on almost every OS known to man.  Once you've been bitten by big
1591     endian vs little endian or IEEE floating point format vs VAX floating
1592     point format or byte addressable memory vs word addressable memory or 32
1593     bit word vs 36 bit word vs 48 bit word vs 64 bit word sizes you get the
1594     message.  All of the data in the file is stored either as ASCII text or
1595     scaled integers (32 bits or smaller), bit-packed and stuffed into an
1596     unsigned character buffer for I/O.  No endian issues, no floating point
1597     issues, no word size issues, no memory mapping issues.  I will be testing
1598     this on x86 Linux, HP-UX, and Micro$oft Windoze.  By the time you read
1599     this it will be portable to those systems at least.
1600 
1601     Now, on to the file layout.  As much as I dislike ASCII it is occasionally
1602     handy to be able to see some information about a file without having to
1603     resort to a special purpose program.  With that in mind I made the first
1604     part of the header of the file ASCII.  The following is an example of the
1605     ASCII portion of the header:
1606 
1607         [VERSION] = PFM Software - tide_db V1.00 - 08/01/02
1608         [LAST MODIFIED] = Thu Aug  1 02:46:29 2002
1609         [HEADER SIZE] = 4096
1610         [NUMBER OF RECORDS] = 10652
1611         [START YEAR] = 1970
1612         [NUMBER OF YEARS] = 68
1613         [SPEED BITS] = 31
1614         [SPEED SCALE] = 10000000
1615         [SPEED OFFSET] = -410667
1616         [EQUILIBRIUM BITS] = 16
1617         [EQUILIBRIUM SCALE] = 100
1618         [EQUILIBRIUM OFFSET] = 0
1619         [NODE BITS] = 15
1620         [NODE SCALE] = 10000
1621         [NODE OFFSET] = -3949
1622         [AMPLITUDE BITS] = 19
1623         [AMPLITUDE SCALE] = 10000
1624         [EPOCH BITS] = 16
1625         [EPOCH SCALE] = 100
1626         [RECORD TYPE BITS] = 4
1627         [LATITUDE BITS] = 25
1628         [LATITUDE SCALE] = 100000
1629         [LONGITUDE BITS] = 26
1630         [LONGITUDE SCALE] = 100000
1631         [RECORD SIZE BITS] = 12
1632         [STATION BITS] = 18
1633         [DATUM OFFSET BITS] = 32
1634         [DATUM OFFSET SCALE] = 10000
1635         [DATE BITS] = 27
1636         [MONTHS ON STATION BITS] = 10
1637         [CONFIDENCE VALUE BITS] = 4
1638         [TIME BITS] = 13
1639         [LEVEL ADD BITS] = 16
1640         [LEVEL ADD SCALE] = 100
1641         [LEVEL MULTIPLY BITS] = 16
1642         [LEVEL MULTIPLY SCALE] = 1000
1643         [DIRECTION BITS] = 9
1644         [LEVEL UNIT BITS] = 3
1645         [LEVEL UNIT TYPES] = 6
1646         [LEVEL UNIT SIZE] = 15
1647         [DIRECTION UNIT BITS] = 2
1648         [DIRECTION UNIT TYPES] = 3
1649         [DIRECTION UNIT SIZE] = 15
1650         [RESTRICTION BITS] = 4
1651         [RESTRICTION TYPES] = 2
1652         [RESTRICTION SIZE] = 30
1653         [PEDIGREE BITS] = 6
1654         [PEDIGREE TYPES] = 13
1655         [PEDIGREE SIZE] = 60
1656         [DATUM BITS] = 7
1657         [DATUM TYPES] = 61
1658         [DATUM SIZE] = 70
1659         [CONSTITUENT BITS] = 8
1660         [CONSTITUENTS] = 173
1661         [CONSTITUENT SIZE] = 10
1662         [COUNTRY BITS] = 9
1663         [COUNTRIES] = 240
1664         [COUNTRY SIZE] = 50
1665         [TZFILE BITS] = 10
1666         [TZFILES] = 449
1667         [TZFILE SIZE] = 30
1668         [END OF FILE] = 2585170
1669         [END OF ASCII HEADER DATA]
1670 
1671     Most of these values will make sense in the context of the following
1672     description of the rest of the file.  Some caveats on the data storage -
1673     if no SCALE is listed for a field, the scale is 1.  If no BITS field is
1674     listed, this is a variable length character field and is stored as 8 bit
1675     ASCII characters.  If no OFFSET is listed, the offset is 0.  Offsets are
1676     scaled.  All SIZE fields refer to the maximum length, in characters, of a
1677     variable length character field.  Some of the BITS fields are calculated
1678     while others are hardwired (see code).  For instance, [DIRECTION BITS] is
1679     hardwired because it is an integer field whose value can only be from 0 to
1680     361 (361 = no direction flag).  [NODE BITS], on the other hand, is
1681     calculated on creation by checking the min, max, and range of all of the
1682     node factor values.  The number of bits needed is easily calculated by
1683     taking the log of the adjusted, scaled range, dividing by the log of 2 and
1684     adding 1.  Immediately following the ASCII portion of the header is a 32
1685     bit checksum of the ASCII portion of the header.  Why?  Because some
1686     genius always gets the idea that he/she can modify the header with a text
1687     or hex editor.  Go figure.
1688 
1689     The rest of the header is as follows :
1690 
1691         [LEVEL UNIT TYPES] fields of [LEVEL UNIT SIZE] characters, each field
1692             is internally 0 terminated (anything after the zero is garbage)
1693 
1694         [DIRECTION UNIT TYPES] fields of [DIRECTION UNIT SIZE] characters, 0
1695             terminated
1696 
1697         [RESTRICTION TYPES] fields of [RESTRICTION SIZE] characters, 0
1698             terminated
1699 
1700         [PEDIGREE TYPES] fields of [PEDIGREE SIZE] characters, 0 terminated
1701 
1702         [TZFILES] fields of [TZFILE SIZE] characters, 0 terminated
1703 
1704         [COUNTRIES] fields of [COUNTRY SIZE] characters, 0 terminated
1705 
1706         [DATUM TYPES] fields of [DATUM SIZE] characters, 0 terminated
1707 
1708         [CONSTITUENTS] fields of [CONSTITUENT SIZE] characters, 0 terminated
1709             Yes, I know, I wasted some space with these fields but I wasn't
1710             worried about a couple of hundred bytes.
1711 
1712         [CONSTITUENTS] fields of [SPEED BITS], speed values (scaled and offset)
1713 
1714         [CONSTITUENTS] groups of [NUMBER OF YEARS] fields of
1715             [EQUILIBRIUM BITS], equilibrium arguments (scaled and offset)
1716 
1717         [CONSTITUENTS] groups of [NUMBER OF YEARS] fields of [NODE BITS], node
1718             factors (scaled and offset)
1719 
1720 
1721     Finally, the data.  At present there are two types of records in the file.
1722     These are reference stations (record type 1) and subordinate stations
1723     (record type 2).  Reference stations contain a set of constituents while
1724     subordinate stations contain a number of offsets to be applied to the
1725     reference station that they are associated with.  Note that reference
1726     stations (record type 1) may, in actuality, be subordinate stations, albeit
1727     with a set of constituents.  All of the records have the following subset
1728     of information stored as the first part of the record:
1729 
1730         [RECORD SIZE BITS] - record size in bytes
1731         [RECORD TYPE BITS] - record type (1 or 2)
1732         [LATITUDE BITS] - latitude (degrees, south negative, scaled & offset)
1733         [LONGITUDE BITS] - longitude (degrees, west negative, scaled & offset)
1734         [TZFILE BITS] - index into timezone array (retrieved from header)
1735         variable size - station name, 0 terminated
1736         [STATION BITS] - record number of reference station or -1
1737         [COUNTRY_BITS] index into country array (retrieved from header)
1738         [PEDIGREE BITS] - index into pedigree array (retrieved from header)
1739         variable size - source, 0 terminated
1740         [RESTRICTION BITS] - index into restriction array
1741         variable size - comments, may contain LFs to indicate newline (no CRs)
1742 
1743 
1744     These are the rest of the fields for record type 1:
1745 
1746         [LEVEL UNIT BITS] - index into level units array
1747         [DATUM OFFSET BITS] - datum offset (scaled)
1748         [DATUM BITS] - index into datum name array
1749         [TIME BITS] - time zone offset from GMT0 (meridian, integer +/-HHMM)
1750         [DATE BITS] - expiration date, (integer YYYYMMDD, default is 0)
1751         [MONTHS ON STATION BITS] - months on station
1752         [DATE BITS] - last date on station, default is 0
1753         [CONFIDENCE BITS] - confidence value (TBD)
1754         [CONSTITUENT BITS] - "N", number of constituents for this station
1755 
1756         N groups of:
1757             [CONSTITUENT BITS] - constituent number
1758             [AMPLITUDE BITS] - amplitude (scaled & offset)
1759             [EPOCH BITS] - epoch (scaled & offset)
1760 
1761 
1762     These are the rest of the fields for record type 2:
1763 
1764         [LEVEL UNIT BITS] - leveladd units, index into level_units array
1765         [DIRECTION UNIT BITS] - direction units, index into dir_units array
1766         [LEVEL UNIT BITS] - avglevel units, index into level_units array
1767         [TIME BITS] - min timeadd (integer +/-HHMM) or 0
1768         [LEVEL ADD BITS] - min leveladd (scaled) or 0
1769         [LEVEL MULTIPLY BITS] - min levelmultiply (scaled) or 0
1770         [LEVEL ADD BITS] - min avglevel (scaled) or 0
1771         [DIRECTION BITS] - min direction (0-360 or 361 for no direction)
1772         [TIME BITS] - max timeadd (integer +/-HHMM) or 0
1773         [LEVEL ADD BITS] - max leveladd (scaled) or 0
1774         [LEVEL MULTIPLY BITS] - max levelmultiply (scaled) or 0
1775         [LEVEL ADD BITS] - max avglevel (scaled) or 0
1776         [DIRECTION BITS] - max direction (0-360 or 361 for no direction)
1777         [TIME BITS] - floodbegins (integer +/-HHMM) or NULLSLACKOFFSET
1778         [TIME BITS] - ebbbegins (integer +/-HHMM) or NULLSLACKOFFSET
1779 
1780 
1781     Back to philosophy!  When you design a database of any kind the first
1782     thing you should ask yourself is "Self, how am I going to access this
1783     data most of the time?".  If you answer yourself out loud you should
1784     consider seeing a shrink.  99 and 44/100ths percent of the time this
1785     database is going to be read to get station data.  The other 66/100ths
1786     percent of the time it will be created/modified.  Variable length records
1787     are no problem on retrieval.  They are no problem to create.  They can be
1788     a major pain in the backside if you have to modify/delete them.  Since we
1789     shouldn't be doing too much editing of the data (usually just adding
1790     records) this is a pretty fair design.  At some point though we are going
1791     to want to modify or delete a record.  There are two possibilities here.
1792     We can dump the database to an ASCII file or files using restore_tide_db,
1793     use a text editor to modify them, and then rebuild the database.  The
1794     other possibility is to modify the record in place.  This is OK if you
1795     don't change a variable length field but what if you want to change the
1796     station name or add a couple of constituents?  With the design as is we
1797     have to read the remainder of the file from the end of the record to be
1798     modified, write the modified record, rewrite the remainder of the file,
1799     and then change the end_of_file pointer in the header.  So, which fields
1800     are going to be a problem?  Changes to station name, source, comments, or
1801     the number of constituents for a station will require a resizing of the
1802     database.  Changes to any of the other fields can be done in place.  The
1803     worst thing that you can do though is to delete a record.  Not just
1804     because the file has to be resized but because it might be a reference
1805     record with subordinate stations.  These would have to be deleted as well.
1806     The delete_tide_record function will do just that so make sure you check
1807     before you call it.  You might not want to do that.
1808 
1809     Another point to note is that when you open the database the records are
1810     indexed at that point.  This takes about half a second on a dual 450.
1811     Most applications use the header part of the record very often and
1812     the rest of the record only if they are going to actually produce
1813     predicted tides.  For instance, XTide plots all of the stations on a
1814     world map or globe and lists all of the station names.  It also needs the
1815     timezone up front.  To save re-indexing to get these values I save them
1816     in memory.  The only time an application needs to actually read an entire
1817     record is when you want to do the prediction.  Otherwise just use
1818     get_partial_tide_record or get_next_partial_tide_record to yank the good
1819     stuff out of memory.
1820 
1821     'Nuff said?
1822 
1823 
1824     See libtcd.html for changelog.
1825 
1826 *****************************************************************************/
1827 
1828 /* Maintenance by DWF */
1829 
1830 
1831 /*  Function prototypes.  */
1832 
1833 NV_U_INT32 calculate_bits (NV_U_INT32 value);
1834 void bit_pack (NV_U_BYTE *, NV_U_INT32, NV_U_INT32, NV_INT32);
1835 NV_U_INT32 bit_unpack (NV_U_BYTE *, NV_U_INT32, NV_U_INT32);
1836 NV_INT32 signed_bit_unpack (NV_U_BYTE buffer[], NV_U_INT32 start,
1837                             NV_U_INT32 numbits);
1838 
1839 
1840 
1841 /*  Global variables.  */
1842 
1843 typedef struct
1844 {
1845     NV_INT32                address;
1846     NV_U_INT32              record_size;
1847     NV_U_INT16              tzfile;
1848     NV_INT32                reference_station;
1849     NV_INT32                lat;
1850     NV_INT32                lon;
1851     NV_U_BYTE               record_type;
1852     NV_CHAR                 *name;
1853 } TIDE_INDEX;
1854 
1855 
1856 static FILE                 *fp = NULL;
1857 static TIDE_INDEX           *tindex = NULL;
1858 static NV_BOOL              modified = NVFalse;
1859 static NV_INT32             current_record, current_index;
1860 static NV_CHAR              filename[MONOLOGUE_LENGTH];
1861 
1862 
1863 /*****************************************************************************\
1864   Checked fread and fwrite wrappers
1865   DWF 2007-12-02
1866 
1867   Fedora package compiles generate warnings for invoking these
1868   functions without checking the return.
1869 \*****************************************************************************/
1870 
chk_fread(void * ptr,size_t size,size_t nmemb,FILE * stream)1871 static void chk_fread (void *ptr, size_t size, size_t nmemb, FILE *stream) {
1872     size_t ret;
1873     ret = fread (ptr, size, nmemb, stream);
1874     if (ret != nmemb) {
1875 //        LOG_ERROR ("libtcd unexpected error: fread failed\n");
1876 //        LOG_ERROR ("nmemb = %lu, got %lu\n", nmemb, ret);
1877         abort();
1878     }
1879 }
1880 
chk_fwrite(const void * ptr,size_t size,size_t nmemb,FILE * stream)1881 static void chk_fwrite (const void *ptr, size_t size, size_t nmemb,
1882                         FILE *stream) {
1883     size_t ret;
1884     ret = fwrite (ptr, size, nmemb, stream);
1885     if (ret != nmemb) {
1886 //        LOG_ERROR ("libtcd unexpected error: fwrite failed\n");
1887 //        LOG_ERROR ("nmemb = %lu, got %lu\n", nmemb, ret);
1888 //        LOG_ERROR ("The database is probably corrupt now.\n");
1889         abort();
1890     }
1891 }
1892 
1893 
1894 /*****************************************************************************\
1895 
1896     Function        dump_tide_record - prints out all of the fields in the
1897                     input tide record
1898 
1899     Synopsis        dump_tide_record (rec);
1900 
1901                     TIDE_RECORD *rec        pointer to the tide record
1902 
1903     Returns         void
1904 
1905     Author          Jan C. Depner
1906     Date            08/01/02
1907 
1908     See libtcd.html for changelog.
1909 
1910 \*****************************************************************************/
1911 
dump_tide_record(const TIDE_RECORD * rec)1912 void dump_tide_record (const TIDE_RECORD *rec)
1913 {
1914     NV_U_INT32              i;
1915 
1916     assert (rec);
1917 
1918     LOG_ERROR ("\n\nRecord number = %d\n", rec->header.record_number);
1919     LOG_ERROR ("Record size = %u\n", rec->header.record_size);
1920     LOG_ERROR ("Record type = %u\n", rec->header.record_type);
1921     LOG_ERROR ("Latitude = %f\n", rec->header.latitude);
1922     LOG_ERROR ("Longitude = %f\n", rec->header.longitude);
1923     LOG_ERROR ("Reference station = %d\n",
1924              rec->header.reference_station);
1925     LOG_ERROR ("Tzfile = %s\n", get_tzfile (rec->header.tzfile));
1926     LOG_ERROR ("Name = %s\n", rec->header.name);
1927 
1928     LOG_ERROR ("Country = %s\n", get_country (rec->country));
1929     LOG_ERROR ("Source = %s\n", rec->source);
1930     LOG_ERROR ("Restriction = %s\n", get_restriction (rec->restriction));
1931     LOG_ERROR ("Comments = %s\n", rec->comments);
1932     LOG_ERROR ("Notes = %s\n", rec->notes);
1933     LOG_ERROR ("Legalese = %s\n",
1934              get_legalese (rec->legalese));
1935     LOG_ERROR ("Station ID context = %s\n", rec->station_id_context);
1936     LOG_ERROR ("Station ID = %s\n", rec->station_id);
1937     LOG_ERROR ("Date imported = %d\n", rec->date_imported);
1938     LOG_ERROR ("Xfields = %s\n", rec->xfields);
1939 
1940     LOG_ERROR ("Direction units = %s\n",
1941              get_dir_units (rec->direction_units));
1942     LOG_ERROR ("Min direction = %d\n", rec->min_direction);
1943     LOG_ERROR ("Max direction = %d\n", rec->max_direction);
1944     LOG_ERROR ("Level units = %s\n", get_level_units (rec->level_units));
1945 
1946     if (rec->header.record_type == REFERENCE_STATION)
1947     {
1948         LOG_ERROR ("Datum offset = %f\n", rec->datum_offset);
1949         LOG_ERROR ("Datum = %s\n", get_datum (rec->datum));
1950         LOG_ERROR ("Zone offset = %d\n", rec->zone_offset);
1951         LOG_ERROR ("Expiration date = %d\n", rec->expiration_date);
1952         LOG_ERROR ("Months on station = %d\n", rec->months_on_station);
1953         LOG_ERROR ("Last date on station = %d\n",
1954                  rec->last_date_on_station);
1955         LOG_ERROR ("Confidence = %d\n", rec->confidence);
1956         for (i = 0 ; i < hd.pub.constituents ; ++i)
1957         {
1958             if (rec->amplitude[i] != 0.0 || rec->epoch[i] != 0.0)
1959             {
1960                 LOG_ERROR ("Amplitude[%d] = %f\n", i, rec->amplitude[i]);
1961                 LOG_ERROR ("Epoch[%d] = %f\n", i, rec->epoch[i]);
1962             }
1963         }
1964     }
1965 
1966     else if (rec->header.record_type == SUBORDINATE_STATION)
1967     {
1968         LOG_ERROR ("Min time add = %d\n", rec->min_time_add);
1969         LOG_ERROR ("Min level add = %f\n", rec->min_level_add);
1970         LOG_ERROR ("Min level multiply = %f\n", rec->min_level_multiply);
1971         LOG_ERROR ("Max time add = %d\n", rec->max_time_add);
1972         LOG_ERROR ("Max level add = %f\n", rec->max_level_add);
1973         LOG_ERROR ("Max level multiply = %f\n", rec->max_level_multiply);
1974         LOG_ERROR ("Flood begins = %d\n", rec->flood_begins);
1975         LOG_ERROR ("Ebb begins = %d\n", rec->ebb_begins);
1976     }
1977 }
1978 
1979 
1980 /*****************************************************************************\
1981 
1982     Function        write_protect - prevent trying to modify TCD files of
1983                     an earlier version.  Nothing to do with file locking.
1984 
1985     David Flater, 2004-10-14.
1986 
1987 \*****************************************************************************/
1988 
write_protect()1989 static void write_protect () {
1990     if (hd.pub.major_rev < LIBTCD_MAJOR_REV) {
1991         LOG_ERROR ("libtcd error: can't modify TCD files created by earlier version.  Use\nrewrite_tide_db to upgrade the TCD file.\n");
1992         exit (-1);
1993     }
1994 }
1995 
1996 
1997 /*****************************************************************************\
1998 
1999     Function        get_country - gets the country field for record "num"
2000 
2001     Synopsis        get_country (num);
2002 
2003                     NV_INT32 num            tide record number
2004 
2005     Returns         NV_CHAR *               country name (associated with
2006                                             ISO 3166-1:1999 2-character
2007                                             country code
2008 
2009     Author          Jan C. Depner
2010     Date            08/01/02
2011 
2012     See libtcd.html for changelog.
2013 
2014 \*****************************************************************************/
2015 
get_country(NV_INT32 num)2016 const NV_CHAR *get_country (NV_INT32 num)
2017 {
2018     if (!fp) {
2019         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2020         exit(-1);
2021     }
2022     if (num >= 0 && num < (NV_INT32)hd.pub.countries) return (hd.country[num]);
2023     return ("Unknown");
2024 }
2025 
2026 
2027 /*****************************************************************************\
2028 
2029     Function        get_tzfile - gets the time zone name for record "num"
2030 
2031     Synopsis        get_tzfile (num);
2032 
2033                     NV_INT32 num            tide record number
2034 
2035     Returns         NV_CHAR *               time zone name used in TZ variable
2036 
2037     Author          Jan C. Depner
2038     Date            08/01/02
2039 
2040     See libtcd.html for changelog.
2041 
2042 \*****************************************************************************/
2043 
get_tzfile(NV_INT32 num)2044 const NV_CHAR *get_tzfile (NV_INT32 num)
2045 {
2046     if (!fp) {
2047         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2048         exit(-1);
2049     }
2050     if (num >= 0 && num < (NV_INT32)hd.pub.tzfiles) return (hd.tzfile[num]);
2051     return ("Unknown");
2052 }
2053 
2054 
2055 /*****************************************************************************\
2056 
2057     Function        get_station - get the name of the station for record "num"
2058 
2059     Synopsis        get_station (num);
2060 
2061                     NV_INT32 num            tide record number
2062 
2063     Returns         NV_CHAR *               station name
2064 
2065     Author          Jan C. Depner
2066     Date            08/01/02
2067 
2068     See libtcd.html for changelog.
2069 
2070 \*****************************************************************************/
2071 
get_station(NV_INT32 num)2072 const NV_CHAR *get_station (NV_INT32 num)
2073 {
2074     if (!fp) {
2075         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2076         exit(-1);
2077     }
2078     if (num >= 0 && num < (NV_INT32)hd.pub.number_of_records) return (tindex[num].name);
2079     return ("Unknown");
2080 }
2081 
2082 
2083 /*****************************************************************************\
2084 
2085     Function        get_constituent - get the constituent name for constituent
2086                     number "num"
2087 
2088     Synopsis        get_constituent (num);
2089 
2090                     NV_INT32 num            constituent number
2091 
2092     Returns         NV_CHAR *               constituent name
2093 
2094     Author          Jan C. Depner
2095     Date            08/01/02
2096 
2097     See libtcd.html for changelog.
2098 
2099 \*****************************************************************************/
2100 
get_constituent(NV_INT32 num)2101 const NV_CHAR *get_constituent (NV_INT32 num)
2102 {
2103     if (!fp) {
2104         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2105         exit(-1);
2106     }
2107     if (num >= 0 && num < (NV_INT32)hd.pub.constituents) return (hd.constituent[num]);
2108     return ("Unknown");
2109 }
2110 
2111 
2112 /*****************************************************************************\
2113 
2114     Function        get_level_units - get the level units for level units
2115                     number "num"
2116 
2117     Synopsis        get_level_units (num);
2118 
2119                     NV_INT32 num            level units number
2120 
2121     Returns         NV_CHAR *               units (ex. "meters");
2122 
2123     Author          Jan C. Depner
2124     Date            08/01/02
2125 
2126     See libtcd.html for changelog.
2127 
2128 \*****************************************************************************/
2129 
get_level_units(NV_INT32 num)2130 const NV_CHAR *get_level_units (NV_INT32 num)
2131 {
2132     if (!fp) {
2133         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2134         exit(-1);
2135     }
2136     if (num >= 0 && num < (NV_INT32)hd.pub.level_unit_types) return (hd.level_unit[num]);
2137     return ("Unknown");
2138 }
2139 
2140 
2141 /*****************************************************************************\
2142 
2143     Function        get_dir_units - get the direction units for direction
2144                     units number "num"
2145 
2146     Synopsis        get_dir_units (num);
2147 
2148                     NV_INT32 num            direction units number
2149 
2150     Returns         NV_CHAR *               units (ex. "degrees true");
2151 
2152     Author          Jan C. Depner
2153     Date            08/01/02
2154 
2155     See libtcd.html for changelog.
2156 
2157 \*****************************************************************************/
2158 
get_dir_units(NV_INT32 num)2159 const NV_CHAR *get_dir_units (NV_INT32 num)
2160 {
2161     if (!fp) {
2162         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2163         exit(-1);
2164     }
2165     if (num >= 0 && num < (NV_INT32)hd.pub.dir_unit_types) return (hd.dir_unit[num]);
2166     return ("Unknown");
2167 }
2168 
2169 
2170 /*****************************************************************************\
2171 
2172     Function        get_restriction - gets the restriction description for
2173                     restriction number "num"
2174 
2175     Synopsis        get_restriction (num);
2176 
2177                     NV_INT32 num            restriction number
2178 
2179     Returns         NV_CHAR *               restriction (ex. "PUBLIC DOMAIN");
2180 
2181     Author          Jan C. Depner
2182     Date            08/01/02
2183 
2184     See libtcd.html for changelog.
2185 
2186 \*****************************************************************************/
2187 
get_restriction(NV_INT32 num)2188 const NV_CHAR *get_restriction (NV_INT32 num)
2189 {
2190     if (!fp) {
2191         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2192         exit(-1);
2193     }
2194     if (num >= 0 && num < (NV_INT32)hd.pub.restriction_types)
2195         return (hd.restriction[num]);
2196     return ("Unknown");
2197 }
2198 
2199 
2200 /*****************************************************************************\
2201 
2202     Function        get_pedigree - gets the pedigree description for pedigree
2203                     number "num"
2204 
2205     Synopsis        get_pedigree (num);
2206 
2207                     NV_INT32 num            pedigree number
2208 
2209     Returns         NV_CHAR *               pedigree description
2210 
2211     Author          Jan C. Depner
2212     Date            08/01/02
2213 
2214     See libtcd.html for changelog.
2215 
2216 \*****************************************************************************/
2217 
2218 #ifdef COMPAT114
get_pedigree(NV_INT32 num)2219 NV_CHAR *get_pedigree (NV_INT32 num) {
2220     return "Unknown";
2221 }
2222 #endif
2223 
2224 
2225 /*****************************************************************************\
2226 
2227     Function        get_datum - gets the datum name for datum number "num"
2228 
2229     Synopsis        get_datum (num);
2230 
2231                     NV_INT32 num            datum number
2232 
2233     Returns         NV_CHAR *               datum name
2234 
2235     Author          Jan C. Depner
2236     Date            08/01/02
2237 
2238     See libtcd.html for changelog.
2239 
2240 \*****************************************************************************/
2241 
get_datum(NV_INT32 num)2242 const NV_CHAR *get_datum (NV_INT32 num)
2243 {
2244     if (!fp) {
2245         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2246         exit(-1);
2247     }
2248     if (num >= 0 && num < (NV_INT32)hd.pub.datum_types) return (hd.datum[num]);
2249     return ("Unknown");
2250 }
2251 
2252 
2253 /*****************************************************************************\
2254 DWF 2004-10-14
2255 \*****************************************************************************/
get_legalese(NV_INT32 num)2256 const NV_CHAR *get_legalese (NV_INT32 num)
2257 {
2258     if (!fp) {
2259         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2260         exit(-1);
2261     }
2262     if (num >= 0 && num < (NV_INT32)hd.pub.legaleses) return (hd.legalese[num]);
2263     return ("Unknown");
2264 }
2265 
2266 
2267 /*****************************************************************************\
2268 
2269     Function        get_speed - gets the speed value for constituent number
2270                     "num"
2271 
2272     Synopsis        get_speed (num);
2273 
2274                     NV_INT32 num            constituent number
2275 
2276     Returns         NV_FLOAT64              speed
2277 
2278     Author          Jan C. Depner
2279     Date            08/01/02
2280 
2281     See libtcd.html for changelog.
2282 
2283 \*****************************************************************************/
2284 
get_speed(NV_INT32 num)2285 NV_FLOAT64 get_speed (NV_INT32 num)
2286 {
2287     if (!fp) {
2288         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2289         exit(-1);
2290     }
2291     assert (num >= 0 && num < (NV_INT32)hd.pub.constituents);
2292     return hd.speed[num];
2293 }
2294 
2295 
2296 /*****************************************************************************\
2297 
2298     Function        get_equilibrium - gets the equilibrium value for
2299                     constituent number "num" and year "year"
2300 
2301     Synopsis        get_equilibrium (num, year);
2302 
2303                     NV_INT32 num            constituent number
2304                     NV_INT32 year           year
2305 
2306     Returns         NV_FLOAT32              equilibrium argument
2307 
2308     Author          Jan C. Depner
2309     Date            08/01/02
2310 
2311     See libtcd.html for changelog.
2312 
2313 \*****************************************************************************/
2314 
get_equilibrium(NV_INT32 num,NV_INT32 year)2315 NV_FLOAT32 get_equilibrium (NV_INT32 num, NV_INT32 year)
2316 {
2317     if (!fp) {
2318         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2319         exit(-1);
2320     }
2321     assert (num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 && year < (NV_INT32)hd.pub.number_of_years);
2322     return hd.equilibrium[num][year];
2323 }
2324 
2325 
2326 /*****************************************************************************\
2327   DWF 2004-10-04
2328 \*****************************************************************************/
get_equilibriums(NV_INT32 num)2329 NV_FLOAT32 *get_equilibriums (NV_INT32 num) {
2330     if (!fp) {
2331         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2332         exit(-1);
2333     }
2334     assert (num >= 0 && num < (NV_INT32)hd.pub.constituents);
2335     return hd.equilibrium[num];
2336 }
2337 
2338 
2339 /*****************************************************************************\
2340 
2341     Function        get_node_factor - gets the node factor value for
2342                     constituent number "num" and year "year"
2343 
2344     Synopsis        get_node_factor (num, year);
2345 
2346                     NV_INT32 num            constituent number
2347                     NV_INT32 year           year
2348 
2349     Returns         NV_FLOAT32              node factor
2350 
2351     Author          Jan C. Depner
2352     Date            08/01/02
2353 
2354     See libtcd.html for changelog.
2355 
2356 \*****************************************************************************/
2357 
get_node_factor(NV_INT32 num,NV_INT32 year)2358 NV_FLOAT32 get_node_factor (NV_INT32 num, NV_INT32 year)
2359 {
2360     if (!fp) {
2361         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2362         exit(-1);
2363     }
2364     assert (num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 && year < (NV_INT32)hd.pub.number_of_years);
2365     return hd.node_factor[num][year];
2366 }
2367 
2368 
2369 /*****************************************************************************\
2370   DWF 2004-10-04
2371 \*****************************************************************************/
get_node_factors(NV_INT32 num)2372 NV_FLOAT32 *get_node_factors (NV_INT32 num) {
2373     if (!fp) {
2374         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2375         exit(-1);
2376     }
2377     assert (num >= 0 && num < (NV_INT32)hd.pub.constituents);
2378     return hd.node_factor[num];
2379 }
2380 
2381 
2382 /*****************************************************************************\
2383 
2384     Function        get_partial_tide_record - gets "header" portion of record
2385                     "num" from the index that is stored in memory.  This is
2386                     way faster than reading it again and we have to read it
2387                     to set up the index.  This costs a bit in terms of
2388                     memory but most applications use this data far more than
2389                     the rest of the record.
2390 
2391     Synopsis        get_partial_tide_record (num, rec);
2392 
2393                     NV_INT32 num              record number
2394                     TIDE_STATION_HEADER *rec  header portion of the record
2395 
2396     Returns         NV_BOOL                   NVTrue if successful
2397 
2398     Author          Jan C. Depner
2399     Date            08/01/02
2400 
2401     See libtcd.html for changelog.
2402 
2403 \*****************************************************************************/
2404 
get_partial_tide_record(NV_INT32 num,TIDE_STATION_HEADER * rec)2405 NV_BOOL get_partial_tide_record (NV_INT32 num, TIDE_STATION_HEADER *rec)
2406 {
2407     if (!fp) {
2408         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2409         return NVFalse;
2410     }
2411 
2412     if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records) return (NVFalse);
2413 
2414     assert (rec);
2415 
2416     rec->record_number = num;
2417     rec->record_size = tindex[num].record_size;
2418     rec->record_type = tindex[num].record_type;
2419     rec->latitude = (NV_FLOAT64) tindex[num].lat / hd.latitude_scale;
2420     rec->longitude = (NV_FLOAT64) tindex[num].lon / hd.longitude_scale;
2421     rec->reference_station = tindex[num].reference_station;
2422     rec->tzfile = tindex[num].tzfile;
2423     strcpy (rec->name, tindex[num].name);
2424 
2425     current_index = num;
2426 
2427     return (NVTrue);
2428 }
2429 
2430 
2431 /*****************************************************************************\
2432 
2433     Function        get_next_partial_tide_record - gets "header" portion of
2434                     the next record from the index that is stored in memory.
2435 
2436     Synopsis        get_next_partial_tide_record (rec);
2437 
2438                     TIDE_STATION_HEADER *rec  header portion of the record
2439 
2440     Returns         NV_INT32                  record number or -1 on failure
2441 
2442     Author          Jan C. Depner
2443     Date            08/01/02
2444 
2445     See libtcd.html for changelog.
2446 
2447 \*****************************************************************************/
2448 
get_next_partial_tide_record(TIDE_STATION_HEADER * rec)2449 NV_INT32 get_next_partial_tide_record (TIDE_STATION_HEADER *rec)
2450 {
2451     if (!get_partial_tide_record (current_index + 1, rec)) return (-1);
2452 
2453     return (current_index);
2454 }
2455 
2456 
2457 /*****************************************************************************\
2458 
2459     Function        get_nearest_partial_tide_record - gets "header" portion of
2460                     the record closest geographically to the input position.
2461 
2462     Synopsis        get_nearest_partial_tide_record (lat, lon, rec);
2463 
2464                     NV_FLOAT64 lat            latitude
2465                     NV_FLOAT64 lon            longitude
2466                     TIDE_STATION_HEADER *rec  header portion of the record
2467 
2468     Returns         NV_INT32                  record number or -1 on failure
2469 
2470     Author          Jan C. Depner
2471     Date            08/01/02
2472 
2473     See libtcd.html for changelog.
2474 
2475 \*****************************************************************************/
2476 
get_nearest_partial_tide_record(NV_FLOAT64 lat,NV_FLOAT64 lon,TIDE_STATION_HEADER * rec)2477 NV_INT32 get_nearest_partial_tide_record (NV_FLOAT64 lat, NV_FLOAT64 lon,
2478         TIDE_STATION_HEADER *rec)
2479 {
2480     NV_FLOAT64           diff, min_diff, lt, ln;
2481     NV_U_INT32             i, shortest = 0;
2482 
2483     min_diff = 999999999.9;
2484     for (i = 0 ; i < hd.pub.number_of_records ; ++i)
2485     {
2486         lt = (NV_FLOAT64) tindex[i].lat / hd.latitude_scale;
2487         ln = (NV_FLOAT64) tindex[i].lon / hd.longitude_scale;
2488 
2489         diff = sqrt ((lat - lt) * (lat - lt) + (lon - ln) * (lon - ln));
2490 
2491         if (diff < min_diff)
2492         {
2493             min_diff = diff;
2494             shortest = i;
2495         }
2496     }
2497 
2498     if (!get_partial_tide_record (shortest, rec)) return (-1);
2499     return (shortest);
2500 }
2501 
2502 
2503 /*****************************************************************************\
2504 
2505     Function        get_time - converts a time string in +/-HH:MM form to an
2506                     integer in +/-HHMM form
2507 
2508     Synopsis        get_time (string);
2509 
2510                     NV_CHAR *string         time string
2511 
2512     Returns         NV_INT32                time
2513 
2514     Author          Jan C. Depner
2515     Date            08/01/02
2516 
2517     See libtcd.html for changelog.
2518 
2519 \*****************************************************************************/
2520 
get_time(const NV_CHAR * string)2521 NV_INT32 get_time (const NV_CHAR *string)
2522 {
2523     NV_INT32        hour, minute, hhmm;
2524 
2525     assert (string);
2526     sscanf (string, "%d:%d", &hour, &minute);
2527 
2528 
2529     /*  Trying to deal with negative 0 (-00:45).  */
2530 
2531     if (string[0] == '-')
2532     {
2533         if (hour < 0) hour = -hour;
2534 
2535         hhmm = -(hour * 100 + minute);
2536     }
2537     else
2538     {
2539         hhmm = hour * 100 + minute;
2540     }
2541 
2542     return (hhmm);
2543 }
2544 
2545 
2546 /*****************************************************************************\
2547 
2548     Function        ret_time - converts a time value in +/-HHMM form to a
2549                     time string in +/-HH:MM form
2550 
2551     Synopsis        ret_time (time);
2552 
2553                     NV_INT32                time
2554 
2555     Returns         NV_CHAR *               time string
2556 
2557     Author          Jan C. Depner
2558     Date            08/01/02
2559 
2560     See libtcd.html for changelog.
2561 
2562 \*****************************************************************************/
2563 
ret_time(NV_INT32 time)2564 NV_CHAR *ret_time (NV_INT32 time)
2565 {
2566     NV_INT32          hour, minute;
2567     static NV_CHAR    tname[16];
2568 
2569     hour = abs (time) / 100;
2570     assert (hour <= 99999 && hour >= -99999); /* 9 chars: +99999:99 */
2571     minute = abs (time) % 100;
2572 
2573     if (time < 0)
2574     {
2575         sprintf (tname, "-%02d:%02d", hour, minute);
2576     }
2577     else
2578     {
2579         sprintf (tname, "+%02d:%02d", hour, minute);
2580     }
2581 
2582     return tname;
2583 }
2584 
2585 
2586 /*****************************************************************************\
2587   DWF 2004-10-04
2588 \*****************************************************************************/
ret_time_neat(NV_INT32 time)2589 NV_CHAR *ret_time_neat (NV_INT32 time)
2590 {
2591     NV_INT32          hour, minute;
2592     static NV_CHAR    tname[16];
2593 
2594     hour = abs (time) / 100;
2595     assert (hour <= 99999 && hour >= -99999); /* 9 chars: +99999:99 */
2596     minute = abs (time) % 100;
2597 
2598     if (time < 0)
2599         sprintf (tname, "-%d:%02d", hour, minute);
2600     else if (time > 0)
2601         sprintf (tname, "+%d:%02d", hour, minute);
2602     else
2603         strcpy (tname, "0:00");
2604 
2605     return tname;
2606 }
2607 
2608 
2609 /*****************************************************************************\
2610   DWF 2004-10-04
2611 \*****************************************************************************/
ret_date(NV_U_INT32 date)2612 NV_CHAR *ret_date (NV_U_INT32 date) {
2613     static NV_CHAR tname[30];
2614     if (!date)
2615         strcpy (tname, "NULL");
2616     else {
2617         unsigned y, m, d;
2618         y = date / 10000;
2619         date %= 10000;
2620         m = date / 100;
2621         d = date % 100;
2622         sprintf (tname, "%4u-%02u-%02u", y, m, d);
2623     }
2624     return tname;
2625 }
2626 
2627 
2628 /*****************************************************************************\
2629 
2630     Function        get_tide_db_header - gets the public portion of the tide
2631                     database header
2632 
2633     Synopsis        get_tide_db_header ();
2634 
2635     Returns         DB_HEADER_PUBLIC        public tide header
2636 
2637     Author          Jan C. Depner
2638     Date            08/01/02
2639 
2640     See libtcd.html for changelog.
2641 
2642 \*****************************************************************************/
2643 
get_tide_db_header()2644 DB_HEADER_PUBLIC get_tide_db_header ()
2645 {
2646     if (!fp) {
2647         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2648         exit(-1);
2649     }
2650     return (hd.pub);
2651 }
2652 
2653 
2654 /*****************************************************************************\
2655    DWF 2004-09-30
2656    Prevent buffer overflows for MONOLOGUE_LENGTH strings.
2657 \*****************************************************************************/
boundscheck_monologue(const NV_CHAR * string)2658 static void boundscheck_monologue (const NV_CHAR *string) {
2659     assert (string);
2660     if (strlen(string) >= MONOLOGUE_LENGTH) {
2661 //        LOG_ERROR ("libtcd fatal error:  static buffer size exceeded\n");
2662 //        LOG_ERROR ("Buffer is size MONOLOGUE_LENGTH (%u)\n",
2663 //                 MONOLOGUE_LENGTH);
2664 //        LOG_ERROR ("String is length %lu\n", strlen(string));
2665 //        LOG_ERROR ("The offending string is:\n%s\n", string);
2666         exit (-1);
2667     }
2668 }
2669 
2670 
2671 /*****************************************************************************\
2672    DWF 2004-09-30
2673    Prevent buffer overflows for ONELINER_LENGTH strings.
2674 \*****************************************************************************/
boundscheck_oneliner(const NV_CHAR * string)2675 static void boundscheck_oneliner (const NV_CHAR *string) {
2676     assert (string);
2677     if (strlen(string) >= ONELINER_LENGTH) {
2678 //        LOG_ERROR ("libtcd fatal error:  static buffer size exceeded\n");
2679 //        LOG_ERROR ("Buffer is size ONELINER_LENGTH (%u)\n",
2680 //                 ONELINER_LENGTH);
2681 //        LOG_ERROR ("String is length %lu\n", strlen(string));
2682 //        LOG_ERROR ("The offending string is:\n%s\n", string);
2683         exit (-1);
2684     }
2685 }
2686 
2687 
2688 /*****************************************************************************\
2689 
2690     Function        clip_string - removes leading and trailing spaces from
2691                     search strings.
2692 
2693     Synopsis        clip_string (string);
2694 
2695                     NV_CHAR *string         search string
2696 
2697     Returns         NV_CHAR *               clipped string
2698 
2699     Author          Jan C. Depner
2700     Date            09/16/02
2701 
2702     See libtcd.html for changelog.
2703 
2704 \*****************************************************************************/
2705 
clip_string(const NV_CHAR * string)2706 static NV_CHAR *clip_string (const NV_CHAR *string)
2707 {
2708     static NV_CHAR        new_string[MONOLOGUE_LENGTH];
2709     NV_INT32              i, l, start = -1, end = -1;
2710 
2711     boundscheck_monologue (string);
2712     new_string[0] = '\0';
2713 
2714     l = (int)strlen(string);
2715     if (l) {
2716         for (i=0; i<l; ++i) {
2717             if (string[i] != ' ') {
2718                 start = i;
2719                 break;
2720             }
2721         }
2722         for (i=l-1; i >= start; --i) {
2723             if (string[i] != ' ' && string[i] != 10 && string[i] != 13) {
2724                 end = i;
2725                 break;
2726             }
2727         }
2728         if (start > -1 && end > -1 && end >= start) {
2729             strncpy (new_string, string+start, end-start+1);
2730             new_string[end-start+1] = '\0';
2731         }
2732     }
2733     return new_string;
2734 }
2735 
2736 
2737 /*****************************************************************************\
2738 
2739     Function        search_station - returns record numbers of all stations
2740                     that have the string "string" anywhere in the station
2741                     name.  This search is case insensitive.  When no more
2742                     records are found it returns -1;
2743 
2744     Synopsis        search_station (string);
2745 
2746                     NV_CHAR *string         search string
2747 
2748     Returns         NV_INT32                record number or -1 when no more
2749                                             matches
2750 
2751     Author          Jan C. Depner
2752     Date            08/01/02
2753 
2754     See libtcd.html for changelog.
2755 
2756 \*****************************************************************************/
2757 
search_station(const NV_CHAR * string)2758 NV_INT32 search_station (const NV_CHAR *string)
2759 {
2760     static NV_CHAR        last_search[ONELINER_LENGTH];
2761     static NV_U_INT32     j=0;
2762     NV_U_INT32            i;
2763     NV_CHAR               name[ONELINER_LENGTH], search[ONELINER_LENGTH];
2764 
2765     if (!fp) {
2766         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2767         return -1;
2768     }
2769 
2770     boundscheck_oneliner (string);
2771 
2772     for (i = 0 ; i < strlen(string) + 1 ; ++i)
2773         search[i] = tolower (string[i]);
2774 
2775     if (strcmp (search, last_search)) j = 0;
2776 
2777     strcpy (last_search, search);
2778 
2779     while (j < hd.pub.number_of_records)
2780     {
2781         for (i = 0 ; i < strlen(tindex[j].name) + 1 ; ++i)
2782             name[i] = tolower (tindex[j].name[i]);
2783 
2784         ++j;
2785         if (strstr (name, search))
2786             return (j - 1);
2787     }
2788 
2789     j = 0;
2790     return -1;
2791 }
2792 
2793 
2794 /*****************************************************************************\
2795 
2796     Function        find_station - finds the record number of the station
2797                     that has name "name"
2798 
2799     Synopsis        find_station (name);
2800 
2801                     NV_CHAR *name           station name
2802 
2803     Returns         NV_INT32                record number
2804 
2805     Author          Jan C. Depner
2806     Date            08/01/02
2807 
2808     See libtcd.html for changelog.
2809 
2810 \*****************************************************************************/
2811 
find_station(const NV_CHAR * name)2812 NV_INT32 find_station (const NV_CHAR *name)
2813 {
2814     NV_U_INT32              i;
2815 
2816     if (!fp) {
2817         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2818         return -1;
2819     }
2820 
2821     assert (name);
2822     for (i = 0 ; i < hd.pub.number_of_records ; ++i)
2823     {
2824         if (!strcmp (name, tindex[i].name)) return (i);
2825     }
2826 
2827     return (-1);
2828 }
2829 
2830 
2831 /*****************************************************************************\
2832 
2833     Function        find_tzfile - gets the timezone number (index into
2834                     tzfile array) given the tzfile name
2835 
2836     Synopsis        find_tzfile (name);
2837 
2838                     NV_CHAR *name          tzfile name
2839 
2840     Returns         NV_INT32                tzfile number
2841 
2842     Author          Jan C. Depner
2843     Date            08/01/02
2844 
2845     See libtcd.html for changelog.
2846 
2847 \*****************************************************************************/
2848 
find_tzfile(const NV_CHAR * name)2849 NV_INT32 find_tzfile (const NV_CHAR *name)
2850 {
2851     NV_INT32   j;
2852     NV_U_INT32 i;
2853     NV_CHAR     *temp;
2854 
2855     if (!fp) {
2856         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2857         return -1;
2858     }
2859 
2860     temp = clip_string(name);
2861 
2862     j = -1;
2863     for (i = 0 ; i < hd.pub.tzfiles ; ++i)
2864     {
2865         if (!strcmp (temp, get_tzfile (i)))
2866         {
2867             j = i;
2868             break;
2869         }
2870     }
2871 
2872     return (j);
2873 }
2874 
2875 
2876 /*****************************************************************************\
2877 
2878     Function        find_country - gets the timezone number (index into
2879                     country array) given the country name
2880 
2881     Synopsis        find_country (name);
2882 
2883                     NV_CHAR *name          country name
2884 
2885     Returns         NV_INT32                country number
2886 
2887     Author          Jan C. Depner
2888     Date            08/01/02
2889 
2890     See libtcd.html for changelog.
2891 
2892 \*****************************************************************************/
2893 
find_country(const NV_CHAR * name)2894 NV_INT32 find_country (const NV_CHAR *name)
2895 {
2896     NV_INT32    j;
2897     NV_U_INT32  i;
2898     NV_CHAR     *temp;
2899 
2900     if (!fp) {
2901         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2902         return -1;
2903     }
2904 
2905     temp = clip_string(name);
2906 
2907     j = -1;
2908     for (i = 0 ; i < hd.pub.countries ; ++i)
2909     {
2910         if (!strcmp (temp, get_country (i)))
2911         {
2912             j = i;
2913             break;
2914         }
2915     }
2916 
2917     return (j);
2918 }
2919 
2920 
2921 /*****************************************************************************\
2922 
2923     Function        find_level_units - gets the index into the level_units
2924                     array given the level units name
2925 
2926     Synopsis        find_level_units (name);
2927 
2928                     NV_CHAR *name          units name (ex. "meters")
2929 
2930     Returns         NV_INT32                units number
2931 
2932     Author          Jan C. Depner
2933     Date            08/01/02
2934 
2935     See libtcd.html for changelog.
2936 
2937 \*****************************************************************************/
2938 
find_level_units(const NV_CHAR * name)2939 NV_INT32 find_level_units (const NV_CHAR *name)
2940 {
2941     NV_INT32    j;
2942     NV_U_INT32  i;
2943     NV_CHAR     *temp;
2944 
2945     if (!fp) {
2946         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2947         return -1;
2948     }
2949 
2950     temp = clip_string(name);
2951 
2952     j = -1;
2953     for (i = 0 ; i < hd.pub.level_unit_types ; ++i)
2954     {
2955         if (!strcmp (get_level_units (i), temp))
2956         {
2957             j = i;
2958             break;
2959         }
2960     }
2961 
2962     return (j);
2963 }
2964 
2965 
2966 /*****************************************************************************\
2967 
2968     Function        find_dir_units - gets the index into the dir_units
2969                     array given the direction units name
2970 
2971     Synopsis        find_dir_units (name);
2972 
2973                     NV_CHAR *name          units name (ex. "degrees true")
2974 
2975     Returns         NV_INT32                units number
2976 
2977     Author          Jan C. Depner
2978     Date            08/01/02
2979 
2980     See libtcd.html for changelog.
2981 
2982 \*****************************************************************************/
2983 
find_dir_units(const NV_CHAR * name)2984 NV_INT32 find_dir_units (const NV_CHAR *name)
2985 {
2986     NV_INT32    j;
2987     NV_U_INT32  i;
2988     NV_CHAR     *temp;
2989 
2990     if (!fp) {
2991         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
2992         return -1;
2993     }
2994 
2995     temp = clip_string(name);
2996 
2997     j = -1;
2998     for (i = 0 ; i < hd.pub.dir_unit_types ; ++i)
2999     {
3000         if (!strcmp (get_dir_units (i), temp))
3001         {
3002             j = i;
3003             break;
3004         }
3005     }
3006 
3007     return (j);
3008 }
3009 
3010 
3011 /*****************************************************************************\
3012 
3013     Function        find_pedigree - gets the index into the pedigree array
3014                     given the pedigree name
3015 
3016     Synopsis        find_pedigree (name);
3017 
3018                     NV_CHAR *name          pedigree name
3019 
3020     Returns         NV_INT32                pedigree number
3021 
3022     Author          Jan C. Depner
3023     Date            08/01/02
3024 
3025     See libtcd.html for changelog.
3026 
3027 \*****************************************************************************/
3028 
3029 #ifdef COMPAT114
find_pedigree(const NV_CHAR * name)3030 NV_INT32 find_pedigree (const NV_CHAR *name) {
3031     return 0;
3032 }
3033 #endif
3034 
3035 
3036 /*****************************************************************************\
3037 
3038     Function        find_datum - gets the index into the datum array given the
3039                     datum name
3040 
3041     Synopsis        find_datum (name);
3042 
3043                     NV_CHAR *name          datum name
3044 
3045     Returns         NV_INT32                datum number
3046 
3047     Author          Jan C. Depner
3048     Date            08/01/02
3049 
3050     See libtcd.html for changelog.
3051 
3052 \*****************************************************************************/
3053 
find_datum(const NV_CHAR * name)3054 NV_INT32 find_datum (const NV_CHAR *name)
3055 {
3056     NV_INT32    j;
3057     NV_U_INT32  i;
3058     NV_CHAR     *temp;
3059 
3060     if (!fp) {
3061         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
3062         return -1;
3063     }
3064 
3065     temp = clip_string(name);
3066 
3067     j = -1;
3068     for (i = 0 ; i < hd.pub.datum_types ; ++i)
3069     {
3070         if (!strcmp (get_datum (i), temp))
3071         {
3072             j = i;
3073             break;
3074         }
3075     }
3076 
3077     return (j);
3078 }
3079 
3080 
3081 /*****************************************************************************\
3082   DWF 2004-10-14
3083 \*****************************************************************************/
find_legalese(const NV_CHAR * name)3084 NV_INT32 find_legalese (const NV_CHAR *name)
3085 {
3086     NV_INT32    j;
3087     NV_U_INT32  i;
3088     NV_CHAR     *temp;
3089 
3090     if (!fp) {
3091         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
3092         return -1;
3093     }
3094 
3095     temp = clip_string(name);
3096 
3097     j = -1;
3098     for (i = 0 ; i < hd.pub.legaleses ; ++i)
3099     {
3100         if (!strcmp (get_legalese (i), temp))
3101         {
3102             j = i;
3103             break;
3104         }
3105     }
3106 
3107     return (j);
3108 }
3109 
3110 
3111 /*****************************************************************************\
3112 
3113     Function        find_constituent - gets the index into the constituent
3114                     arrays for the named constituent.
3115 
3116     Synopsis        find_constituent (name);
3117 
3118                     NV_CHAR *name           constituent name (ex. M2)
3119 
3120     Returns         NV_INT32                index into constituent arrays or -1
3121                                             on failure
3122 
3123     Author          Jan C. Depner
3124     Date            08/01/02
3125 
3126     See libtcd.html for changelog.
3127 
3128 \*****************************************************************************/
3129 
find_constituent(const NV_CHAR * name)3130 NV_INT32 find_constituent (const NV_CHAR *name)
3131 {
3132     NV_U_INT32               i;
3133     NV_CHAR     *temp;
3134 
3135     if (!fp) {
3136         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
3137         return -1;
3138     }
3139 
3140     temp = clip_string(name);
3141 
3142     for (i = 0 ; i < hd.pub.constituents ; ++i)
3143     {
3144         if (!strcmp (get_constituent (i), temp)) return (i);
3145     }
3146 
3147     return (-1);
3148 }
3149 
3150 
3151 /*****************************************************************************\
3152 
3153     Function        find_restriction - gets the index into the restriction
3154                     array given the restriction name
3155 
3156     Synopsis        find_restriction (name);
3157 
3158                     NV_CHAR *name          restriction name
3159 
3160     Returns         NV_INT32                restriction number
3161 
3162     Author          Jan C. Depner
3163     Date            08/01/02
3164 
3165     See libtcd.html for changelog.
3166 
3167 \*****************************************************************************/
3168 
find_restriction(const NV_CHAR * name)3169 NV_INT32 find_restriction (const NV_CHAR *name)
3170 {
3171     NV_INT32    j;
3172     NV_U_INT32  i;
3173     NV_CHAR     *temp;
3174 
3175     if (!fp) {
3176         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
3177         return -1;
3178     }
3179 
3180     temp = clip_string(name);
3181 
3182     j = -1;
3183     for (i = 0 ; i < hd.pub.restriction_types ; ++i)
3184     {
3185         if (!strcmp (get_restriction (i), temp))
3186         {
3187             j = i;
3188             break;
3189         }
3190     }
3191     return (j);
3192 }
3193 
3194 
3195 /*****************************************************************************\
3196 
3197     Function        set_speed - sets the speed value for constituent "num"
3198 
3199     Synopsis        set_speed (num, value);
3200 
3201                     NV_INT32 num            constituent number
3202                     NV_FLOAT64 value        speed value
3203 
3204     Returns         void
3205 
3206     Author          Jan C. Depner
3207     Date            08/01/02
3208 
3209     See libtcd.html for changelog.
3210 
3211 \*****************************************************************************/
3212 
set_speed(NV_INT32 num,NV_FLOAT64 value)3213 void set_speed (NV_INT32 num, NV_FLOAT64 value)
3214 {
3215     if (!fp) {
3216         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
3217         exit (-1);
3218     }
3219     write_protect();
3220     assert (num >= 0 && num < (NV_INT32)hd.pub.constituents);
3221     if (value < 0.0) {
3222         LOG_ERROR ("libtcd set_speed: somebody tried to set a negative speed (%f)\n", value);
3223         exit (-1);
3224     }
3225     hd.speed[num] = value;
3226     modified = NVTrue;
3227 }
3228 
3229 
3230 /*****************************************************************************\
3231 
3232     Function        set_equilibrium - sets the equilibrium argument for
3233                     constituent "num" and year "year"
3234 
3235     Synopsis        set_equilibrium (num, year, value);
3236 
3237                     NV_INT32 num            constituent number
3238                     NV_INT32 year           year
3239                     NV_FLOAT64 value        equilibrium argument
3240 
3241     Returns         void
3242 
3243     Author          Jan C. Depner
3244     Date            08/01/02
3245 
3246     See libtcd.html for changelog.
3247 
3248 \*****************************************************************************/
3249 
set_equilibrium(NV_INT32 num,NV_INT32 year,NV_FLOAT32 value)3250 void set_equilibrium (NV_INT32 num, NV_INT32 year, NV_FLOAT32 value)
3251 {
3252     if (!fp) {
3253         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
3254         exit (-1);
3255     }
3256     write_protect();
3257     assert (num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 && year < (NV_INT32)hd.pub.number_of_years);
3258     hd.equilibrium[num][year] = value;
3259     modified = NVTrue;
3260 }
3261 
3262 
3263 /*****************************************************************************\
3264 
3265     Function        set_node_factor - sets the node factor for constituent
3266                     "num" and year "year"
3267 
3268     Synopsis        set_node_factor (num, year, value);
3269 
3270                     NV_INT32 num            constituent number
3271                     NV_INT32 year           year
3272                     NV_FLOAT64 value        node factor
3273 
3274     Returns         void
3275 
3276     Author          Jan C. Depner
3277     Date            08/01/02
3278 
3279     See libtcd.html for changelog.
3280 
3281 \*****************************************************************************/
3282 
set_node_factor(NV_INT32 num,NV_INT32 year,NV_FLOAT32 value)3283 void set_node_factor (NV_INT32 num, NV_INT32 year, NV_FLOAT32 value)
3284 {
3285     if (!fp) {
3286         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
3287         exit (-1);
3288     }
3289     write_protect();
3290     assert (num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 && year < (NV_INT32)hd.pub.number_of_years);
3291     if (value <= 0.0) {
3292         LOG_ERROR ("libtcd set_node_factor: somebody tried to set a negative or zero node factor (%f)\n", value);
3293         exit (-1);
3294     }
3295     hd.node_factor[num][year] = value;
3296     modified = NVTrue;
3297 }
3298 
3299 
3300 /*****************************************************************************\
3301 
3302     Function        add_pedigree - adds a new pedigree to the database
3303 
3304     Synopsis        add_pedigree (name, db);
3305 
3306                     NV_CHAR *name          new pedigree string
3307                     DB_HEADER_PUBLIC *db    modified header
3308 
3309     Returns         NV_INT32                new pedigree index
3310 
3311     Author          Jan C. Depner
3312     Date            09/20/02
3313 
3314     See libtcd.html for changelog.
3315 
3316 \*****************************************************************************/
3317 
3318 #ifdef COMPAT114
add_pedigree(const NV_CHAR * name,const DB_HEADER_PUBLIC * db)3319 NV_INT32 add_pedigree (const NV_CHAR *name, const DB_HEADER_PUBLIC *db) {
3320     return 0;
3321 }
3322 #endif
3323 
3324 
3325 /*****************************************************************************\
3326 
3327     Function        add_tzfile - adds a new tzfile to the database
3328 
3329     Synopsis        add_tzfile (name, db);
3330 
3331                     NV_CHAR *name          new tzfile string
3332                     DB_HEADER_PUBLIC *db    modified header
3333 
3334     Returns         NV_INT32                new tzfile index
3335 
3336     Author          Jan C. Depner
3337     Date            09/20/02
3338 
3339     See libtcd.html for changelog.
3340 
3341 \*****************************************************************************/
3342 
add_tzfile(const NV_CHAR * name,DB_HEADER_PUBLIC * db)3343 NV_INT32 add_tzfile (const NV_CHAR *name, DB_HEADER_PUBLIC *db)
3344 {
3345     NV_CHAR *c_name;
3346 
3347     if (!fp) {
3348         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
3349         exit (-1);
3350     }
3351     write_protect();
3352 
3353     assert (name);
3354     if (strlen(name) + 1 > hd.tzfile_size) {
3355         LOG_ERROR ("libtcd error: tzfile exceeds size limit (%u).\n",
3356                  hd.tzfile_size);
3357         LOG_ERROR ("The offending input is: %s\n", name);
3358         exit (-1);
3359     }
3360 
3361     if (hd.pub.tzfiles == hd.max_tzfiles)
3362     {
3363         LOG_ERROR ("You have exceeded the maximum number of tzfile types!\n");
3364         LOG_ERROR ("You cannot add any new tzfile types.\n");
3365         LOG_ERROR ("Modify the DEFAULT_TZFILE_BITS and rebuild the database.\n");
3366         exit (-1);
3367     }
3368 
3369     c_name = clip_string (name);
3370 
3371     hd.tzfile[hd.pub.tzfiles] = (NV_CHAR *) calloc (strlen (c_name) + 1,
3372                                 sizeof (NV_CHAR));
3373 
3374     if (hd.tzfile[hd.pub.tzfiles] == NULL)
3375     {
3376         perror ("Allocating new tzfile string");
3377         exit (-1);
3378     }
3379 
3380     strcpy (hd.tzfile[hd.pub.tzfiles++], c_name);
3381     if (db)
3382         *db = hd.pub;
3383     modified = NVTrue;
3384     return (hd.pub.tzfiles - 1);
3385 }
3386 
3387 
3388 /*****************************************************************************\
3389 
3390     Function        add_country - adds a new country to the database
3391 
3392     Synopsis        add_country (name, db);
3393 
3394                     NV_CHAR *name          new country string
3395                     DB_HEADER_PUBLIC *db    modified header
3396 
3397     Returns         NV_INT32                new country index
3398 
3399     Author          Jan C. Depner
3400     Date            09/20/02
3401 
3402     See libtcd.html for changelog.
3403 
3404 \*****************************************************************************/
3405 
add_country(const NV_CHAR * name,DB_HEADER_PUBLIC * db)3406 NV_INT32 add_country (const NV_CHAR *name, DB_HEADER_PUBLIC *db)
3407 {
3408     NV_CHAR *c_name;
3409 
3410     if (!fp) {
3411         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
3412         exit (-1);
3413     }
3414     write_protect();
3415 
3416     assert (name);
3417     if (strlen(name) + 1 > hd.country_size) {
3418         LOG_ERROR ("libtcd error: country exceeds size limit (%u).\n",
3419                  hd.country_size);
3420         LOG_ERROR ("The offending input is: %s\n", name);
3421         exit (-1);
3422     }
3423 
3424     if (hd.pub.countries == hd.max_countries)
3425     {
3426         LOG_ERROR ("You have exceeded the maximum number of country names!\n");
3427         LOG_ERROR ("You cannot add any new country names.\n");
3428         LOG_ERROR ("Modify the DEFAULT_COUNTRY_BITS and rebuild the database.\n");
3429         exit (-1);
3430     }
3431 
3432     c_name = clip_string (name);
3433 
3434     hd.country[hd.pub.countries] = (NV_CHAR *) calloc (strlen (c_name) + 1,
3435                                    sizeof (NV_CHAR));
3436 
3437     if (hd.country[hd.pub.countries] == NULL)
3438     {
3439         perror ("Allocating new country string");
3440         exit (-1);
3441     }
3442 
3443     strcpy (hd.country[hd.pub.countries++], c_name);
3444     if (db)
3445         *db = hd.pub;
3446     modified = NVTrue;
3447     return (hd.pub.countries - 1);
3448 }
3449 
3450 
3451 /*****************************************************************************\
3452 
3453     Function        add_datum - adds a new datum to the database
3454 
3455     Synopsis        add_datum (name, db);
3456 
3457                     NV_CHAR *name          new datum string
3458                     DB_HEADER_PUBLIC *db    modified header
3459 
3460     Returns         NV_INT32                new datum index
3461 
3462     Author          Jan C. Depner
3463     Date            09/20/02
3464 
3465     See libtcd.html for changelog.
3466 
3467 \*****************************************************************************/
3468 
add_datum(const NV_CHAR * name,DB_HEADER_PUBLIC * db)3469 NV_INT32 add_datum (const NV_CHAR *name, DB_HEADER_PUBLIC *db)
3470 {
3471     NV_CHAR *c_name;
3472 
3473     if (!fp) {
3474         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
3475         exit (-1);
3476     }
3477     write_protect();
3478 
3479     assert (name);
3480     if (strlen(name) + 1 > hd.datum_size) {
3481         LOG_ERROR ("libtcd error: datum exceeds size limit (%u).\n",
3482                  hd.datum_size);
3483         LOG_ERROR ("The offending input is: %s\n", name);
3484         exit (-1);
3485     }
3486 
3487     if (hd.pub.datum_types == hd.max_datum_types)
3488     {
3489         LOG_ERROR ("You have exceeded the maximum number of datum types!\n");
3490         LOG_ERROR ("You cannot add any new datum types.\n");
3491         LOG_ERROR ("Modify the DEFAULT_DATUM_BITS and rebuild the database.\n");
3492         exit (-1);
3493     }
3494 
3495     c_name = clip_string (name);
3496 
3497     hd.datum[hd.pub.datum_types] = (NV_CHAR *) calloc (strlen (c_name) + 1,
3498                                    sizeof (NV_CHAR));
3499 
3500     if (hd.datum[hd.pub.datum_types] == NULL)
3501     {
3502         perror ("Allocating new datum string");
3503         exit (-1);
3504     }
3505 
3506     strcpy (hd.datum[hd.pub.datum_types++], c_name);
3507     if (db)
3508         *db = hd.pub;
3509     modified = NVTrue;
3510     return (hd.pub.datum_types - 1);
3511 }
3512 
3513 
3514 /*****************************************************************************\
3515   DWF 2004-10-14
3516 \*****************************************************************************/
add_legalese(const NV_CHAR * name,DB_HEADER_PUBLIC * db)3517 NV_INT32 add_legalese (const NV_CHAR *name, DB_HEADER_PUBLIC *db)
3518 {
3519     NV_CHAR *c_name;
3520 
3521     if (!fp) {
3522         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
3523         exit (-1);
3524     }
3525     write_protect();
3526 
3527     assert (name);
3528     if (strlen(name) + 1 > hd.legalese_size) {
3529         LOG_ERROR ("libtcd error: legalese exceeds size limit (%u).\n",
3530                  hd.legalese_size);
3531         LOG_ERROR ("The offending input is: %s\n", name);
3532         exit (-1);
3533     }
3534 
3535     if (hd.pub.legaleses == hd.max_legaleses)
3536     {
3537         LOG_ERROR ("You have exceeded the maximum number of legaleses!\n");
3538         LOG_ERROR ("You cannot add any new legaleses.\n");
3539         LOG_ERROR ("Modify the DEFAULT_LEGALESE_BITS and rebuild the database.\n");
3540         exit (-1);
3541     }
3542 
3543     c_name = clip_string (name);
3544 
3545     hd.legalese[hd.pub.legaleses] = (NV_CHAR *) calloc (strlen (c_name) + 1,
3546                                     sizeof (NV_CHAR));
3547 
3548     if (hd.legalese[hd.pub.legaleses] == NULL)
3549     {
3550         perror ("Allocating new legalese string");
3551         exit (-1);
3552     }
3553 
3554     strcpy (hd.legalese[hd.pub.legaleses++], c_name);
3555     if (db)
3556         *db = hd.pub;
3557     modified = NVTrue;
3558     return (hd.pub.legaleses - 1);
3559 }
3560 
3561 
3562 /*****************************************************************************\
3563 
3564     Function        add_restriction - adds a new restriction to the database
3565 
3566     Synopsis        add_restriction (name, db);
3567 
3568                     NV_CHAR *name          new restriction string
3569                     DB_HEADER_PUBLIC *db    modified header
3570 
3571     Returns         NV_INT32                new restriction index
3572 
3573     Author          Jan C. Depner
3574     Date            09/20/02
3575 
3576     See libtcd.html for changelog.
3577 
3578 \*****************************************************************************/
3579 
add_restriction(const NV_CHAR * name,DB_HEADER_PUBLIC * db)3580 NV_INT32 add_restriction (const NV_CHAR *name, DB_HEADER_PUBLIC *db)
3581 {
3582     NV_CHAR *c_name;
3583 
3584     if (!fp) {
3585         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
3586         exit (-1);
3587     }
3588     write_protect();
3589 
3590     assert (name);
3591     if (strlen(name) + 1 > hd.restriction_size) {
3592         LOG_ERROR ("libtcd error: restriction exceeds size limit (%u).\n",
3593                  hd.restriction_size);
3594         LOG_ERROR ("The offending input is: %s\n", name);
3595         exit (-1);
3596     }
3597 
3598     if (hd.pub.restriction_types == hd.max_restriction_types)
3599     {
3600         LOG_ERROR ("You have exceeded the maximum number of restriction types!\n");
3601         LOG_ERROR ("You cannot add any new restriction types.\n");
3602         LOG_ERROR ("Modify the DEFAULT_RESTRICTION_BITS and rebuild the database.\n");
3603         exit (-1);
3604     }
3605 
3606     c_name = clip_string (name);
3607 
3608     hd.restriction[hd.pub.restriction_types] =
3609         (NV_CHAR *) calloc (strlen (c_name) + 1, sizeof (NV_CHAR));
3610 
3611     if (hd.restriction[hd.pub.restriction_types] == NULL)
3612     {
3613         perror ("Allocating new restriction string");
3614         exit (-1);
3615     }
3616 
3617     strcpy (hd.restriction[hd.pub.restriction_types++], c_name);
3618     if (db)
3619         *db = hd.pub;
3620     modified = NVTrue;
3621     return (hd.pub.restriction_types - 1);
3622 }
3623 
3624 
3625 /*****************************************************************************\
3626   DWF 2004-10-04
3627 \*****************************************************************************/
find_or_add_restriction(const NV_CHAR * name,DB_HEADER_PUBLIC * db)3628 NV_INT32 find_or_add_restriction (const NV_CHAR *name, DB_HEADER_PUBLIC *db) {
3629     NV_INT32 ret;
3630     ret = find_restriction (name);
3631     if (ret < 0)
3632         ret = add_restriction (name, db);
3633     assert (ret >= 0);
3634     return ret;
3635 }
3636 
3637 
3638 /*****************************************************************************\
3639   DWF 2004-10-04
3640 \*****************************************************************************/
find_or_add_tzfile(const NV_CHAR * name,DB_HEADER_PUBLIC * db)3641 NV_INT32 find_or_add_tzfile (const NV_CHAR *name, DB_HEADER_PUBLIC *db) {
3642     NV_INT32 ret;
3643     ret = find_tzfile (name);
3644     if (ret < 0)
3645         ret = add_tzfile (name, db);
3646     assert (ret >= 0);
3647     return ret;
3648 }
3649 
3650 
3651 /*****************************************************************************\
3652   DWF 2004-10-04
3653 \*****************************************************************************/
find_or_add_country(const NV_CHAR * name,DB_HEADER_PUBLIC * db)3654 NV_INT32 find_or_add_country (const NV_CHAR *name, DB_HEADER_PUBLIC *db) {
3655     NV_INT32 ret;
3656     ret = find_country (name);
3657     if (ret < 0)
3658         ret = add_country (name, db);
3659     assert (ret >= 0);
3660     return ret;
3661 }
3662 
3663 
3664 /*****************************************************************************\
3665   DWF 2004-10-04
3666 \*****************************************************************************/
find_or_add_datum(const NV_CHAR * name,DB_HEADER_PUBLIC * db)3667 NV_INT32 find_or_add_datum (const NV_CHAR *name, DB_HEADER_PUBLIC *db) {
3668     NV_INT32 ret;
3669     ret = find_datum (name);
3670     if (ret < 0)
3671         ret = add_datum (name, db);
3672     assert (ret >= 0);
3673     return ret;
3674 }
3675 
3676 
3677 /*****************************************************************************\
3678   DWF 2004-10-14
3679 \*****************************************************************************/
find_or_add_legalese(const NV_CHAR * name,DB_HEADER_PUBLIC * db)3680 NV_INT32 find_or_add_legalese (const NV_CHAR *name, DB_HEADER_PUBLIC *db) {
3681     NV_INT32 ret;
3682     ret = find_legalese (name);
3683     if (ret < 0)
3684         ret = add_legalese (name, db);
3685     assert (ret >= 0);
3686     return ret;
3687 }
3688 
3689 
3690 /*****************************************************************************\
3691 
3692     Function        check_simple - checks tide record to see if it is a
3693                     "simple" subordinate station.
3694 
3695     Synopsis        check_simple (rec);
3696 
3697                     TIDE_RECORD rec         tide record
3698 
3699     Returns         NV_BOOL                 NVTrue if "simple"
3700 
3701     Author          Jan C. Depner
3702     Date            08/01/02
3703 
3704     See libtcd.html for changelog.
3705 
3706     "Simplified" type 2 records were done away with 2003-03-27 per the
3707     discussion in http://www.flaterco.com/xtide/tcd_notes.html.  This
3708     function is now of interest only in restore_tide_db, which uses it
3709     to determine which XML format to output.  Deprecated here, moved
3710     to restore_tide_db.
3711 
3712 \*****************************************************************************/
3713 
3714 #ifdef COMPAT114
check_simple(TIDE_RECORD rec)3715 NV_BOOL check_simple (TIDE_RECORD rec)
3716 {
3717     if (rec.max_time_add       == rec.min_time_add        &&
3718             rec.max_level_add      == rec.min_level_add       &&
3719             rec.max_level_multiply == rec.min_level_multiply  &&
3720             rec.max_avg_level == 0   &&
3721             rec.min_avg_level == 0   &&
3722             rec.max_direction == 361 &&
3723             rec.min_direction == 361 &&
3724             rec.flood_begins  == NULLSLACKOFFSET &&
3725             rec.ebb_begins    == NULLSLACKOFFSET)
3726         return (NVTrue);
3727 
3728     return (NVFalse);
3729 }
3730 #endif
3731 
3732 
3733 /*****************************************************************************\
3734 
3735     Function        header_checksum - compute the checksum for the ASCII
3736                     portion of the database header
3737 
3738     Synopsis        header_checksum ();
3739 
3740     Returns         NV_U_INT32              checksum value
3741 
3742     Author          Jan C. Depner
3743     Date            08/01/02
3744 
3745     See libtcd.html for changelog.
3746 
3747 \*****************************************************************************/
3748 
header_checksum()3749 static NV_U_INT32 header_checksum ()
3750 {
3751     NV_U_INT32          checksum, i, save_pos;
3752     NV_U_BYTE           *buf;
3753     NV_U_INT32          crc_table[256] =
3754     {   0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,
3755         0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,
3756         0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,0x1DB71064,0x6AB020F2,
3757         0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7,
3758         0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,
3759         0xFA0F3D63,0x8D080DF5,0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,
3760         0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C,
3761         0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,
3762         0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,
3763         0xCFBA9599,0xB8BDA50F,0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,
3764         0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D,0x76DC4190,0x01DB7106,
3765         0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433,
3766         0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,
3767         0x91646C97,0xE6635C01,0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,
3768         0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,
3769         0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,
3770         0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,
3771         0xA4D1C46D,0xD3D6F4FB,0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,
3772         0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,0x5005713C,0x270241AA,
3773         0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F,
3774         0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,
3775         0xB7BD5C3B,0xC0BA6CAD,0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,
3776         0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,
3777         0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,
3778         0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,
3779         0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,
3780         0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,0xD6D6A3E8,0xA1D1937E,
3781         0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,
3782         0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,
3783         0x316E8EEF,0x4669BE79,0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,
3784         0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,
3785         0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,
3786         0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,
3787         0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,
3788         0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,0x86D3D2D4,0xF1D4E242,
3789         0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,
3790         0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,
3791         0x616BFFD3,0x166CCF45,0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,
3792         0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,0xAED16A4A,0xD9D65ADC,
3793         0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9,
3794         0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,
3795         0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,
3796         0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D
3797     };
3798 
3799     if (!fp) {
3800         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
3801         exit (-1);
3802     }
3803 
3804     save_pos = ftell (fp);
3805 
3806     fseek (fp, 0, SEEK_SET);
3807 
3808     if ((buf = (NV_U_BYTE *) calloc (hd.header_size, sizeof (NV_U_BYTE))) ==
3809             NULL)
3810     {
3811         perror ("Allocating checksum buffer");
3812         exit (-1);
3813     }
3814 
3815     checksum = ~0;
3816 
3817     assert (hd.header_size > 0);
3818     chk_fread (buf, hd.header_size, 1, fp);
3819     for (i = 0 ; i < (NV_U_INT32)hd.header_size ; ++i)
3820     {
3821         checksum = crc_table[(checksum ^ buf[i]) & 0xff] ^ (checksum >> 8);
3822     }
3823     checksum ^= ~0;
3824 
3825     free (buf);
3826 
3827     fseek (fp, save_pos, SEEK_SET);
3828 
3829     return (checksum);
3830 }
3831 
3832 
3833 /*****************************************************************************\
3834 
3835     Function        old_header_checksum - compute the old-style checksum for
3836                     the ASCII portion of the database header just in case this
3837                     is a pre 1.02 file.
3838 
3839     Synopsis        old_header_checksum ();
3840 
3841     Returns         NV_U_INT32              checksum value
3842 
3843     Author          Jan C. Depner
3844     Date            11/15/02
3845 
3846 \*****************************************************************************/
3847 
3848 #ifdef COMPAT114
old_header_checksum()3849 static NV_U_INT32 old_header_checksum ()
3850 {
3851     NV_U_INT32          checksum, i, save_pos;
3852     NV_U_BYTE           *buf;
3853 
3854     if (!fp) {
3855         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
3856         exit (-1);
3857     }
3858 
3859     save_pos = ftell (fp);
3860 
3861     checksum = 0;
3862 
3863     fseek (fp, 0, SEEK_SET);
3864 
3865     if ((buf = (NV_U_BYTE *) calloc (hd.header_size, sizeof (NV_U_BYTE))) ==
3866             NULL)
3867     {
3868         perror ("Allocating checksum buffer");
3869         exit (-1);
3870     }
3871 
3872     chk_fread (buf, hd.header_size, 1, fp);
3873 
3874     for (i = 0 ; i < hd.header_size ; ++i) checksum += buf[i];
3875 
3876     free (buf);
3877 
3878     fseek (fp, save_pos, SEEK_SET);
3879 
3880     return (checksum);
3881 }
3882 #endif
3883 
3884 
3885 /*****************************************************************************\
3886    DWF 2004-10-01
3887    Get current time in preferred format.
3888 \*****************************************************************************/
curtime()3889 static NV_CHAR *curtime () {
3890     static NV_CHAR buf[ONELINER_LENGTH];
3891     time_t t = time(NULL);
3892     require (strftime (buf, ONELINER_LENGTH, "%Y-%m-%d %H:%M %Z", localtime(&t)) > 0);
3893     return buf;
3894 }
3895 
3896 
3897 /*****************************************************************************\
3898    DWF 2004-10-15
3899    Calculate bytes for number of bits.
3900 \*****************************************************************************/
bits2bytes(NV_U_INT32 nbits)3901 static NV_U_INT32 bits2bytes (NV_U_INT32 nbits) {
3902     if (nbits % 8)
3903         return nbits / 8 + 1;
3904     return nbits / 8;
3905 }
3906 
3907 
3908 /*****************************************************************************\
3909 
3910     Function        write_tide_db_header - writes the database header to the
3911                     file
3912 
3913     Synopsis        write_tide_db_header ();
3914 
3915     Returns         void
3916 
3917     Author          Jan C. Depner
3918     Date            08/01/02
3919 
3920     See libtcd.html for changelog.
3921 
3922 \*****************************************************************************/
3923 
write_tide_db_header()3924 static void write_tide_db_header ()
3925 {
3926     NV_U_INT32          i, size, pos;
3927     NV_INT32            start, temp_int;
3928     static NV_CHAR      zero = 0;
3929     NV_U_BYTE           *buf, checksum_c[4];
3930 
3931     if (!fp) {
3932         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
3933         exit (-1);
3934     }
3935     write_protect();
3936 
3937     fseek (fp, 0, SEEK_SET);
3938 
3939     fprintf (fp, "[VERSION] = %s\n", LIBTCD_VERSION);
3940     fprintf (fp, "[MAJOR REV] = %u\n", LIBTCD_MAJOR_REV);
3941     fprintf (fp, "[MINOR REV] = %u\n", LIBTCD_MINOR_REV);
3942 
3943     fprintf (fp, "[LAST MODIFIED] = %s\n", curtime());
3944 
3945     fprintf (fp, "[HEADER SIZE] = %u\n", hd.header_size);
3946     fprintf (fp, "[NUMBER OF RECORDS] = %u\n", hd.pub.number_of_records);
3947 
3948     fprintf (fp, "[START YEAR] = %d\n", hd.pub.start_year);
3949     fprintf (fp, "[NUMBER OF YEARS] = %u\n", hd.pub.number_of_years);
3950 
3951     fprintf (fp, "[SPEED BITS] = %u\n", hd.speed_bits);
3952     fprintf (fp, "[SPEED SCALE] = %u\n", hd.speed_scale);
3953     fprintf (fp, "[SPEED OFFSET] = %d\n", hd.speed_offset);
3954     fprintf (fp, "[EQUILIBRIUM BITS] = %u\n", hd.equilibrium_bits);
3955     fprintf (fp, "[EQUILIBRIUM SCALE] = %u\n", hd.equilibrium_scale);
3956     fprintf (fp, "[EQUILIBRIUM OFFSET] = %d\n", hd.equilibrium_offset);
3957     fprintf (fp, "[NODE BITS] = %u\n", hd.node_bits);
3958     fprintf (fp, "[NODE SCALE] = %u\n", hd.node_scale);
3959     fprintf (fp, "[NODE OFFSET] = %d\n", hd.node_offset);
3960     fprintf (fp, "[AMPLITUDE BITS] = %u\n", hd.amplitude_bits);
3961     fprintf (fp, "[AMPLITUDE SCALE] = %u\n", hd.amplitude_scale);
3962     fprintf (fp, "[EPOCH BITS] = %u\n", hd.epoch_bits);
3963     fprintf (fp, "[EPOCH SCALE] = %u\n", hd.epoch_scale);
3964 
3965     fprintf (fp, "[RECORD TYPE BITS] = %u\n", hd.record_type_bits);
3966     fprintf (fp, "[LATITUDE BITS] = %u\n", hd.latitude_bits);
3967     fprintf (fp, "[LATITUDE SCALE] = %u\n", hd.latitude_scale);
3968     fprintf (fp, "[LONGITUDE BITS] = %u\n", hd.longitude_bits);
3969     fprintf (fp, "[LONGITUDE SCALE] = %u\n", hd.longitude_scale);
3970     fprintf (fp, "[RECORD SIZE BITS] = %u\n", hd.record_size_bits);
3971 
3972     fprintf (fp, "[STATION BITS] = %u\n", hd.station_bits);
3973 
3974     fprintf (fp, "[DATUM OFFSET BITS] = %u\n", hd.datum_offset_bits);
3975     fprintf (fp, "[DATUM OFFSET SCALE] = %u\n", hd.datum_offset_scale);
3976     fprintf (fp, "[DATE BITS] = %u\n", hd.date_bits);
3977     fprintf (fp, "[MONTHS ON STATION BITS] = %u\n",
3978              hd.months_on_station_bits);
3979     fprintf (fp, "[CONFIDENCE VALUE BITS] = %u\n", hd.confidence_value_bits);
3980 
3981     fprintf (fp, "[TIME BITS] = %u\n", hd.time_bits);
3982     fprintf (fp, "[LEVEL ADD BITS] = %u\n", hd.level_add_bits);
3983     fprintf (fp, "[LEVEL ADD SCALE] = %u\n", hd.level_add_scale);
3984     fprintf (fp, "[LEVEL MULTIPLY BITS] = %u\n", hd.level_multiply_bits);
3985     fprintf (fp, "[LEVEL MULTIPLY SCALE] = %u\n", hd.level_multiply_scale);
3986     fprintf (fp, "[DIRECTION BITS] = %u\n", hd.direction_bits);
3987 
3988     fprintf (fp, "[LEVEL UNIT BITS] = %u\n", hd.level_unit_bits);
3989     fprintf (fp, "[LEVEL UNIT TYPES] = %u\n", hd.pub.level_unit_types);
3990     fprintf (fp, "[LEVEL UNIT SIZE] = %u\n", hd.level_unit_size);
3991 
3992     fprintf (fp, "[DIRECTION UNIT BITS] = %u\n", hd.dir_unit_bits);
3993     fprintf (fp, "[DIRECTION UNIT TYPES] = %u\n", hd.pub.dir_unit_types);
3994     fprintf (fp, "[DIRECTION UNIT SIZE] = %u\n", hd.dir_unit_size);
3995 
3996     fprintf (fp, "[RESTRICTION BITS] = %u\n", hd.restriction_bits);
3997     fprintf (fp, "[RESTRICTION TYPES] = %u\n", hd.pub.restriction_types);
3998     fprintf (fp, "[RESTRICTION SIZE] = %u\n", hd.restriction_size);
3999 
4000     fprintf (fp, "[DATUM BITS] = %u\n", hd.datum_bits);
4001     fprintf (fp, "[DATUM TYPES] = %u\n", hd.pub.datum_types);
4002     fprintf (fp, "[DATUM SIZE] = %u\n", hd.datum_size);
4003 
4004     fprintf (fp, "[LEGALESE BITS] = %u\n", hd.legalese_bits);
4005     fprintf (fp, "[LEGALESE TYPES] = %u\n", hd.pub.legaleses);
4006     fprintf (fp, "[LEGALESE SIZE] = %u\n", hd.legalese_size);
4007 
4008     fprintf (fp, "[CONSTITUENT BITS] = %u\n", hd.constituent_bits);
4009     fprintf (fp, "[CONSTITUENTS] = %u\n", hd.pub.constituents);
4010     fprintf (fp, "[CONSTITUENT SIZE] = %u\n", hd.constituent_size);
4011 
4012     fprintf (fp, "[TZFILE BITS] = %u\n", hd.tzfile_bits);
4013     fprintf (fp, "[TZFILES] = %u\n", hd.pub.tzfiles);
4014     fprintf (fp, "[TZFILE SIZE] = %u\n", hd.tzfile_size);
4015 
4016     fprintf (fp, "[COUNTRY BITS] = %u\n", hd.country_bits);
4017     fprintf (fp, "[COUNTRIES] = %u\n", hd.pub.countries);
4018     fprintf (fp, "[COUNTRY SIZE] = %u\n", hd.country_size);
4019 
4020     fprintf (fp, "[END OF FILE] = %u\n", hd.end_of_file);
4021     fprintf (fp, "[END OF ASCII HEADER DATA]\n");
4022 
4023 
4024     /*  Fill the remainder of the [HEADER SIZE] ASCII header with zeroes.  */
4025 
4026     start = ftell (fp);
4027     assert (start >= 0);
4028     for (i = start ; i < hd.header_size ; ++i) chk_fwrite (&zero, 1, 1, fp);
4029     fflush (fp);
4030 
4031 
4032     /*  Compute and save the checksum. */
4033 
4034     bit_pack (checksum_c, 0, 32, header_checksum ());
4035     chk_fwrite (checksum_c, 4, 1, fp);
4036 
4037 
4038     /*  NOTE : Using strcpy for character strings (no endian issue).  */
4039 
4040     /*  Write level units.  */
4041 
4042     pos = 0;
4043     size = hd.pub.level_unit_types * hd.level_unit_size;
4044 
4045     if ((buf = (NV_U_BYTE *) calloc (size, sizeof (NV_U_BYTE))) == NULL)
4046     {
4047         perror ("Allocating unit write buffer");
4048         exit (-1);
4049     }
4050     memset (buf, 0, size);
4051 
4052     for (i = 0 ; i < hd.pub.level_unit_types ; ++i)
4053     {
4054         assert (strlen(hd.level_unit[i]) + 1 <= hd.level_unit_size);
4055         strcpy ((NV_CHAR *) &buf[pos], hd.level_unit[i]);
4056         pos += hd.level_unit_size;
4057     }
4058 
4059     chk_fwrite (buf, pos, 1, fp);
4060     free (buf);
4061 
4062 
4063     /*  Write direction units.  */
4064 
4065     pos = 0;
4066     size = hd.pub.dir_unit_types * hd.dir_unit_size;
4067 
4068     if ((buf = (NV_U_BYTE *) calloc (size, sizeof (NV_U_BYTE))) == NULL)
4069     {
4070         perror ("Allocating unit write buffer");
4071         exit (-1);
4072     }
4073     memset (buf, 0, size);
4074 
4075     for (i = 0 ; i < hd.pub.dir_unit_types ; ++i)
4076     {
4077         assert (strlen(hd.dir_unit[i]) + 1 <= hd.dir_unit_size);
4078         strcpy ((NV_CHAR *) &buf[pos], hd.dir_unit[i]);
4079         pos += hd.dir_unit_size;
4080     }
4081 
4082     chk_fwrite (buf, pos, 1, fp);
4083     free (buf);
4084 
4085 
4086     /*  Write restrictions.  */
4087 
4088     pos = 0;
4089     size = hd.max_restriction_types * hd.restriction_size;
4090 
4091     if ((buf = (NV_U_BYTE *) calloc (size, sizeof (NV_U_BYTE))) == NULL)
4092     {
4093         perror ("Allocating restriction write buffer");
4094         exit (-1);
4095     }
4096     memset (buf, 0, size);
4097 
4098     for (i = 0 ; i < hd.max_restriction_types ; ++i)
4099     {
4100         if (i == hd.pub.restriction_types) break;
4101         assert (strlen(hd.restriction[i]) + 1 <= hd.restriction_size);
4102         strcpy ((NV_CHAR *) &buf[pos], hd.restriction[i]);
4103         pos += hd.restriction_size;
4104     }
4105     memcpy (&buf[pos], "__END__", 7);
4106 
4107     chk_fwrite (buf, size, 1, fp);
4108     free (buf);
4109 
4110 
4111     /*  Write tzfiles.  */
4112 
4113     pos = 0;
4114     size = hd.max_tzfiles * hd.tzfile_size;
4115 
4116     if ((buf = (NV_U_BYTE *) calloc (size, sizeof (NV_U_BYTE))) == NULL)
4117     {
4118         perror ("Allocating tzfile write buffer");
4119         exit (-1);
4120     }
4121     memset (buf, 0, size);
4122 
4123     for (i = 0 ; i < hd.max_tzfiles ; ++i)
4124     {
4125         if (i == hd.pub.tzfiles) break;
4126         assert (strlen(hd.tzfile[i]) + 1 <= hd.tzfile_size);
4127         strcpy ((NV_CHAR *) &buf[pos], hd.tzfile[i]);
4128         pos += hd.tzfile_size;
4129     }
4130     memcpy (&buf[pos], "__END__", 7);
4131 
4132     chk_fwrite (buf, size, 1, fp);
4133     free (buf);
4134 
4135 
4136     /*  Write countries.  */
4137 
4138     pos = 0;
4139     size = hd.max_countries * hd.country_size;
4140 
4141     if ((buf = (NV_U_BYTE *) calloc (size, sizeof (NV_U_BYTE))) == NULL)
4142     {
4143         perror ("Allocating country write buffer");
4144         exit (-1);
4145     }
4146     memset (buf, 0, size);
4147 
4148     for (i = 0 ; i < hd.max_countries ; ++i)
4149     {
4150         if (i == hd.pub.countries) break;
4151         assert (strlen(hd.country[i]) + 1 <= hd.country_size);
4152         strcpy ((NV_CHAR *) &buf[pos], hd.country[i]);
4153         pos += hd.country_size;
4154     }
4155     memcpy (&buf[pos], "__END__", 7);
4156 
4157     chk_fwrite (buf, size, 1, fp);
4158     free (buf);
4159 
4160 
4161     /*  Write datums.  */
4162 
4163     pos = 0;
4164     size = hd.max_datum_types * hd.datum_size;
4165 
4166     if ((buf = (NV_U_BYTE *) calloc (size, sizeof (NV_U_BYTE))) == NULL)
4167     {
4168         perror ("Allocating datum write buffer");
4169         exit (-1);
4170     }
4171     memset (buf, 0, size);
4172 
4173     for (i = 0 ; i < hd.max_datum_types ; ++i)
4174     {
4175         if (i == hd.pub.datum_types) break;
4176         assert (strlen(hd.datum[i]) + 1 <= hd.datum_size);
4177         strcpy ((NV_CHAR *) &buf[pos], hd.datum[i]);
4178         pos += hd.datum_size;
4179     }
4180     memcpy (&buf[pos], "__END__", 7);
4181 
4182     chk_fwrite (buf, size, 1, fp);
4183     free (buf);
4184 
4185 
4186     /*  Write legaleses.  */
4187 
4188     pos = 0;
4189     size = hd.max_legaleses * hd.legalese_size;
4190 
4191     if ((buf = (NV_U_BYTE *) calloc (size, sizeof (NV_U_BYTE))) == NULL)
4192     {
4193         perror ("Allocating legalese write buffer");
4194         exit (-1);
4195     }
4196     memset (buf, 0, size);
4197 
4198     for (i = 0 ; i < hd.max_legaleses ; ++i)
4199     {
4200         if (i == hd.pub.legaleses) break;
4201         assert (strlen(hd.legalese[i]) + 1 <= hd.legalese_size);
4202         strcpy ((NV_CHAR *) &buf[pos], hd.legalese[i]);
4203         pos += hd.legalese_size;
4204     }
4205     memcpy (&buf[pos], "__END__", 7);
4206 
4207     chk_fwrite (buf, size, 1, fp);
4208     free (buf);
4209 
4210 
4211     /*  Write constituent names.  */
4212 
4213     pos = 0;
4214     size = hd.pub.constituents * hd.constituent_size;
4215 
4216     if ((buf = (NV_U_BYTE *) calloc (size, sizeof (NV_U_BYTE))) == NULL)
4217     {
4218         perror ("Allocating constituent write buffer");
4219         exit (-1);
4220     }
4221     memset (buf, 0, size);
4222 
4223     for (i = 0 ; i < hd.pub.constituents ; ++i)
4224     {
4225         assert (strlen(hd.constituent[i]) + 1 <= hd.constituent_size);
4226         strcpy ((NV_CHAR *) &buf[pos], hd.constituent[i]);
4227         pos += hd.constituent_size;
4228     }
4229 
4230     chk_fwrite (buf, pos, 1, fp);
4231     free (buf);
4232 
4233 
4234     /*  NOTE : Using bit_pack for integers.  */
4235 
4236     /*  Write speeds.  */
4237 
4238     pos = 0;
4239     size = bits2bytes (hd.pub.constituents * hd.speed_bits);
4240 
4241     if ((buf = (NV_U_BYTE *) calloc (size, sizeof (NV_U_BYTE))) == NULL)
4242     {
4243         perror ("Allocating speed write buffer");
4244         exit (-1);
4245     }
4246     memset (buf, 0, size);
4247 
4248     for (i = 0 ; i < hd.pub.constituents ; ++i)
4249     {
4250         temp_int = NINT (hd.speed[i] * hd.speed_scale) - hd.speed_offset;
4251         assert (temp_int >= 0);
4252         bit_pack (buf, pos, hd.speed_bits, temp_int);
4253         pos += hd.speed_bits;
4254     }
4255 
4256     chk_fwrite (buf, size, 1, fp);
4257     free (buf);
4258 
4259 
4260     /*  Write equilibrium arguments.  */
4261 
4262     pos = 0;
4263     size = bits2bytes (hd.pub.constituents *  hd.pub.number_of_years *
4264                        hd.equilibrium_bits);
4265 
4266     if ((buf = (NV_U_BYTE *) calloc (size, sizeof (NV_U_BYTE))) == NULL)
4267     {
4268         perror ("Allocating equilibrium write buffer");
4269         exit (-1);
4270     }
4271     memset (buf, 0, size);
4272 
4273     for (i = 0 ; i < hd.pub.constituents ; ++i)
4274     {
4275         NV_U_INT32 j;
4276         for (j = 0 ; j < hd.pub.number_of_years ; ++j)
4277         {
4278             temp_int = NINT (hd.equilibrium[i][j] * hd.equilibrium_scale) -
4279                        hd.equilibrium_offset;
4280             assert (temp_int >= 0);
4281             bit_pack (buf, pos, hd.equilibrium_bits, temp_int);
4282             pos += hd.equilibrium_bits;
4283         }
4284     }
4285 
4286     chk_fwrite (buf, size, 1, fp);
4287     free (buf);
4288 
4289 
4290     /*  Write node factors.  */
4291 
4292     pos = 0;
4293     size = bits2bytes (hd.pub.constituents * hd.pub.number_of_years *
4294                        hd.node_bits);
4295 
4296     if ((buf = (NV_U_BYTE *) calloc (size, sizeof (NV_U_BYTE))) == NULL)
4297     {
4298         perror ("Allocating node write buffer");
4299         exit (-1);
4300     }
4301     memset (buf, 0, size);
4302 
4303     for (i = 0 ; i < hd.pub.constituents ; ++i)
4304     {
4305         NV_U_INT32 j;
4306         for (j = 0 ; j < hd.pub.number_of_years ; ++j)
4307         {
4308             temp_int = NINT (hd.node_factor[i][j] * hd.node_scale) -
4309                        hd.node_offset;
4310             assert (temp_int >= 0);
4311             bit_pack (buf, pos, hd.node_bits, temp_int);
4312             pos += hd.node_bits;
4313         }
4314     }
4315 
4316     chk_fwrite (buf, size, 1, fp);
4317     free (buf);
4318 }
4319 
4320 
4321 /*****************************************************************************\
4322 
4323     Function        unpack_string - Safely unpack a string into a
4324                     fixed-length buffer.
4325 
4326     Synopsis        unpack_string (buf, bufsize, pos, outbuf, outbuflen, desc);
4327 
4328                     NV_U_BYTE *buf          input buffer
4329                     NV_U_INT32 bufsize      size of input buffer in bytes
4330                     NV_U_INT32 *pos         current bit-position in buf
4331                                             (in-out parameter)
4332                     NV_CHAR *outbuf         fixed-length string-buffer
4333                     NV_U_INT32 outbuflen    size of outbuf in bytes
4334                     NV_CHAR *desc           description of the field being
4335                                             unpacked for use in warning
4336                                             messages when truncation occurs
4337 
4338     Returns         void
4339 
4340     Author          David Flater
4341     Date            2004-09-30
4342 
4343     pos will be left at the start of the next field even if the string
4344     gets truncated.
4345 
4346 \*****************************************************************************/
4347 
unpack_string(NV_U_BYTE * buf,NV_U_INT32 bufsize,NV_U_INT32 * pos,NV_CHAR * outbuf,NV_U_INT32 outbuflen,const NV_CHAR * desc)4348 static void unpack_string (NV_U_BYTE *buf, NV_U_INT32 bufsize, NV_U_INT32 *pos,
4349                            NV_CHAR *outbuf, NV_U_INT32 outbuflen, const NV_CHAR *desc) {
4350     NV_U_INT32 i;
4351     NV_CHAR c = 'x';
4352     assert (buf);
4353     assert (pos);
4354     assert (outbuf);
4355     assert (desc);
4356     assert (outbuflen);
4357     --outbuflen;
4358     bufsize <<= 3;
4359     for (i = 0 ; c ; ++i) {
4360         assert (*pos < bufsize); /* Catch unterminated strings */
4361         c = bit_unpack (buf, *pos, 8);
4362         (*pos) += 8;
4363         if (i < outbuflen) {
4364             outbuf[i] = c;
4365         } else if (i == outbuflen) {
4366             outbuf[i] = '\0';
4367             if (c) {
4368                 LOG_ERROR ("libtcd warning: truncating overlong %s\n", desc);
4369                 LOG_ERROR ("The offending string starts with:\n%s\n", outbuf);
4370             }
4371         }
4372     }
4373 }
4374 
4375 
4376 /*****************************************************************************\
4377 
4378     Function        unpack_partial_tide_record - unpacks the "header" portion
4379                     of a tide record from the supplied buffer
4380 
4381     Synopsis        unpack_partial_tide_record (buf, rec, pos);
4382 
4383                     NV_U_BYTE *buf          input buffer
4384                     NV_U_INT32 bufsize      size of input buffer in bytes
4385                     TIDE_RECORD *rec        tide record
4386                     NV_U_INT32 *pos         final position in buffer after
4387                                             unpacking the header
4388 
4389     Returns         void
4390 
4391     Author          Jan C. Depner
4392     Date            08/01/02
4393 
4394     See libtcd.html for changelog.
4395 
4396 \*****************************************************************************/
4397 
unpack_partial_tide_record(NV_U_BYTE * buf,NV_U_INT32 bufsize,TIDE_RECORD * rec,NV_U_INT32 * pos)4398 static void unpack_partial_tide_record (NV_U_BYTE *buf, NV_U_INT32 bufsize,
4399                                         TIDE_RECORD *rec, NV_U_INT32 *pos)
4400 {
4401     NV_INT32 temp_int;
4402 
4403     assert (buf);
4404     assert (rec);
4405     assert (pos);
4406 
4407     *pos = 0;
4408 
4409     rec->header.record_size = bit_unpack (buf, *pos, hd.record_size_bits);
4410     *pos += hd.record_size_bits;
4411 
4412     rec->header.record_type = bit_unpack (buf, *pos, hd.record_type_bits);
4413     *pos += hd.record_type_bits;
4414 
4415     temp_int = signed_bit_unpack (buf, *pos, hd.latitude_bits);
4416     rec->header.latitude = (NV_FLOAT64) temp_int / hd.latitude_scale;
4417     *pos += hd.latitude_bits;
4418 
4419     temp_int = signed_bit_unpack (buf, *pos, hd.longitude_bits);
4420     rec->header.longitude = (NV_FLOAT64) temp_int / hd.longitude_scale;
4421     *pos += hd.longitude_bits;
4422 
4423     /* This ordering doesn't match everywhere else but there's no technical
4424        reason to change it from its V1 ordering. */
4425 
4426     rec->header.tzfile = bit_unpack (buf, *pos, hd.tzfile_bits);
4427     *pos += hd.tzfile_bits;
4428 
4429     unpack_string (buf, bufsize, pos, rec->header.name, ONELINER_LENGTH, "station name");
4430 
4431     rec->header.reference_station =
4432         signed_bit_unpack (buf, *pos, hd.station_bits);
4433     *pos += hd.station_bits;
4434 
4435     assert (*pos <= bufsize*8);
4436 }
4437 
4438 
4439 /*****************************************************************************\
4440 
4441     Function        read_partial_tide_record - reads the "header" portion
4442                     of a tide record from the database.  This is used to index
4443                     the database on opening.
4444 
4445     Synopsis        read_partial_tide_record (num, rec);
4446 
4447                     NV_INT32 num            record number
4448                     TIDE_RECORD *rec        tide record
4449 
4450     Returns         NV_INT32                record number read
4451 
4452     Author          Jan C. Depner
4453     Date            08/01/02
4454 
4455     See libtcd.html for changelog.
4456 
4457 \*****************************************************************************/
4458 
read_partial_tide_record(NV_INT32 num,TIDE_RECORD * rec)4459 static NV_INT32 read_partial_tide_record (NV_INT32 num, TIDE_RECORD *rec)
4460 {
4461     NV_U_BYTE               *buf;
4462     NV_U_INT32              maximum_possible_size, pos;
4463 
4464     if (!fp) {
4465         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
4466         exit (-1);
4467     }
4468 
4469     assert (rec);
4470 
4471     /*  Read just the record size, record type, position, time zone, and
4472         name.  */
4473 
4474     maximum_possible_size = hd.record_size_bits + hd.record_type_bits +
4475                             hd.latitude_bits + hd.longitude_bits + hd.tzfile_bits +
4476                             (ONELINER_LENGTH * 8) + hd.station_bits;
4477     maximum_possible_size = bits2bytes (maximum_possible_size);
4478 
4479     if ((buf = (NV_U_BYTE *) calloc (maximum_possible_size, sizeof (NV_U_BYTE))) == NULL)
4480     {
4481         perror ("Allocating partial tide record buffer");
4482         exit (-1);
4483     }
4484 
4485     current_record = num;
4486     fseek (fp, tindex[num].address, SEEK_SET);
4487     /* DWF 2007-12-02:  This is the one place where a short read would not
4488        necessarily mean catastrophe.  We don't know how long the partial
4489        record actually is yet, and it's possible that the full record will
4490        be shorter than maximum_possible_size. */
4491     size_t size = fread (buf, 1, maximum_possible_size, fp);
4492     unpack_partial_tide_record (buf, size, rec, &pos);
4493     free (buf);
4494     return (num);
4495 }
4496 
4497 
4498 /*****************************************************************************\
4499 
4500     Function        read_tide_db_header - reads the tide database header
4501 
4502     Synopsis        read_tide_db_header ();
4503 
4504     Returns         NV_BOOL                 NVTrue if header is correct
4505 
4506     Author          Jan C. Depner
4507     Date            08/01/02
4508 
4509     See libtcd.html for changelog.
4510 
4511 \*****************************************************************************/
4512 
read_tide_db_header()4513 static NV_BOOL read_tide_db_header ()
4514 {
4515     NV_INT32            temp_int;
4516     NV_CHAR             varin[ONELINER_LENGTH], *info;
4517     NV_U_INT32          utemp, i, j, pos, size, key_count;
4518     NV_U_BYTE           *buf, checksum_c[5];
4519     TIDE_RECORD         rec;
4520 
4521     if (!fp) {
4522         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
4523         exit (-1);
4524     }
4525 
4526     strcpy (hd.pub.version, "NO VERSION");
4527 
4528     /*  Compute the number of key phrases there are to match.  */
4529     key_count = sizeof (keys) / sizeof (KEY);
4530 
4531     /*  Zero out the header structure.  */
4532     memset (&hd, 0, sizeof (hd));
4533 
4534     /*  Handle the ASCII header data.  */
4535     while (fgets (varin, sizeof(varin), fp) != NULL)
4536     {
4537         if (strlen (varin) == ONELINER_LENGTH-1) {
4538             if (varin[ONELINER_LENGTH-2] != '\n') {
4539                 LOG_ERROR ("libtcd error:  header line too long, begins with:\n");
4540                 LOG_ERROR ("%s\n", varin);
4541                 LOG_ERROR ("in file %s\n", filename);
4542                 LOG_ERROR ("Configured limit is %u\n", ONELINER_LENGTH-1);
4543                 fclose (fp);
4544                 return NVFalse;
4545             }
4546         }
4547 
4548         if (strstr (varin, "[END OF ASCII HEADER DATA]")) break;
4549 
4550         /* All other lines must be field = value */
4551         info = strchr (varin, '=');
4552         if (!info) {
4553             LOG_ERROR ("libtcd error:  invalid tide db header line:\n");
4554             LOG_ERROR ("%s", varin);
4555             LOG_ERROR ("in file %s\n", filename);
4556             fclose (fp);
4557             return NVFalse;
4558         }
4559         ++info;
4560 
4561         /* Scan the fields per "keys" defined in tide_db_header.h. */
4562         for (i=0; i<key_count; ++i) {
4563             if (strstr (varin, keys[i].keyphrase)) {
4564                 if (!strcmp (keys[i].datatype, "cstr"))
4565                     strcpy ((char *)keys[i].address.cstr, clip_string(info));
4566                 else if (!strcmp (keys[i].datatype, "i32")) {
4567                     if (sscanf (info, "%d", keys[i].address.i32) != 1) {
4568                         LOG_ERROR ("libtcd error:  invalid tide db header line:\n");
4569                         LOG_ERROR ("%s", varin);
4570                         LOG_ERROR ("in file %s\n", filename);
4571                         fclose (fp);
4572                         return NVFalse;
4573                     }
4574                 } else if (!strcmp (keys[i].datatype, "ui32")) {
4575                     if (sscanf (info, "%u", keys[i].address.ui32) != 1) {
4576                         LOG_ERROR ("libtcd error:  invalid tide db header line:\n");
4577                         LOG_ERROR ("%s", varin);
4578                         LOG_ERROR ("in file %s\n", filename);
4579                         fclose (fp);
4580                         return NVFalse;
4581                     }
4582                 } else
4583                     assert (0);
4584             }
4585         }
4586     }
4587 
4588     /*  We didn't get a valid version string.  */
4589 
4590     if (!strcmp (hd.pub.version, "NO VERSION"))
4591     {
4592         LOG_ERROR ("libtcd error:  no version found in tide db header\n");
4593         LOG_ERROR ("in file %s\n", filename);
4594         fclose (fp);
4595         return NVFalse;
4596     }
4597 
4598     /* If no major or minor rev, they're 0 (pre-1.99) */
4599     if (hd.pub.major_rev > LIBTCD_MAJOR_REV) {
4600         LOG_ERROR ("libtcd error:  major revision in TCD file (%u) exceeds major revision of\n", hd.pub.major_rev);
4601         LOG_ERROR ("libtcd (%u).  You must upgrade libtcd to read this file.\n", LIBTCD_MAJOR_REV);
4602         fclose (fp);
4603         return NVFalse;
4604     }
4605 
4606     /*  Move to end of ASCII header.  */
4607     fseek (fp, hd.header_size, SEEK_SET);
4608 
4609 
4610     /*  Read and check the checksum. */
4611 
4612     chk_fread (checksum_c, 4, 1, fp);
4613     utemp = bit_unpack (checksum_c, 0, 32);
4614 
4615     if (utemp != header_checksum ()) {
4616 #ifdef COMPAT114
4617         if (utemp != old_header_checksum ()) {
4618             LOG_ERROR ("libtcd error:  header checksum error in file %s\n", filename);
4619             LOG_ERROR ("Someone may have modified the ASCII portion of the header (don't do that),\n\
4620 or it may just be corrupt.\n");
4621             fclose (fp);
4622             return NVFalse;
4623         }
4624 #else
4625         LOG_ERROR ("libtcd error:  header checksum error in file %s\n", filename);
4626         LOG_ERROR ("Someone may have modified the ASCII portion of the header (don't do that),\n\
4627 or it may be an ancient pre-version-1.02 TCD file, or it may just be corrupt.\n\
4628 Pre-version-1.02 TCD files can be read by building libtcd with COMPAT114\n\
4629 defined.\n");
4630         fclose (fp);
4631         return NVFalse;
4632 #endif
4633     }
4634     fseek (fp, hd.header_size + 4, SEEK_SET);
4635 
4636 
4637     /*  Set the max possible restriction types based on the number of bits
4638         used.  */
4639 
4640     hd.max_restriction_types = NINT (pow (2.0,
4641                                           (NV_FLOAT64) hd.restriction_bits));
4642 
4643 
4644     /*  Set the max possible tzfiles based on the number of bits used.  */
4645 
4646     hd.max_tzfiles = NINT (pow (2.0, (NV_FLOAT64) hd.tzfile_bits));
4647 
4648 
4649     /*  Set the max possible countries based on the number of bits used.  */
4650 
4651     hd.max_countries = NINT (pow (2.0, (NV_FLOAT64) hd.country_bits));
4652 
4653 
4654     /*  Set the max possible datum types based on the number of bits
4655         used.  */
4656 
4657     hd.max_datum_types = NINT (pow (2.0, (NV_FLOAT64) hd.datum_bits));
4658 
4659 
4660     /*  Set the max possible legaleses based on the number of bits
4661         used.  */
4662 
4663     if (hd.pub.major_rev < 2)
4664         hd.max_legaleses = 1;
4665     else
4666         hd.max_legaleses = NINT (pow (2.0, (NV_FLOAT64) hd.legalese_bits));
4667 
4668 
4669     /*  NOTE : Using strcpy for character strings (no endian issue).  */
4670 
4671     /*  Read level units.  */
4672 
4673     hd.level_unit = (NV_CHAR **) calloc (hd.pub.level_unit_types,
4674                                          sizeof (NV_CHAR *));
4675 
4676     if ((buf = (NV_U_BYTE *) calloc (hd.level_unit_size,
4677                                      sizeof (NV_U_BYTE))) == NULL)
4678     {
4679         perror ("Allocating level unit read buffer");
4680         exit (-1);
4681     }
4682 
4683     for (i = 0 ; i < hd.pub.level_unit_types ; ++i)
4684     {
4685         chk_fread (buf, hd.level_unit_size, 1, fp);
4686         hd.level_unit[i] = (NV_CHAR *) calloc (strlen((char*)buf) + 1,
4687                                                sizeof (NV_CHAR));
4688         strcpy (hd.level_unit[i], (NV_CHAR *) buf);
4689     }
4690     free (buf);
4691 
4692 
4693 
4694     /*  Read direction units.  */
4695 
4696     hd.dir_unit = (NV_CHAR **) calloc (hd.pub.dir_unit_types,
4697                                        sizeof (NV_CHAR *));
4698 
4699     if ((buf = (NV_U_BYTE *) calloc (hd.dir_unit_size, sizeof (NV_U_BYTE))) ==
4700             NULL)
4701     {
4702         perror ("Allocating dir unit read buffer");
4703         exit (-1);
4704     }
4705 
4706     for (i = 0 ; i < hd.pub.dir_unit_types ; ++i)
4707     {
4708         chk_fread (buf, hd.dir_unit_size, 1, fp);
4709         hd.dir_unit[i] = (NV_CHAR *) calloc (strlen((char*)buf) + 1,
4710                                              sizeof (NV_CHAR));
4711         strcpy (hd.dir_unit[i], (NV_CHAR *) buf);
4712     }
4713     free (buf);
4714 
4715 
4716 
4717     /*  Read restrictions.  */
4718 
4719     utemp = ftell (fp);
4720     hd.restriction = (NV_CHAR **) calloc (hd.max_restriction_types,
4721                                           sizeof (NV_CHAR *));
4722 
4723     if ((buf = (NV_U_BYTE *) calloc (hd.restriction_size,
4724                                      sizeof (NV_U_BYTE))) == NULL)
4725     {
4726         perror ("Allocating restriction read buffer");
4727         exit (-1);
4728     }
4729 
4730     hd.pub.restriction_types = 0;
4731     for (i = 0 ; i < hd.max_restriction_types ; ++i)
4732     {
4733         chk_fread (buf, hd.restriction_size, 1, fp);
4734         if (!strcmp ((char*)buf, "__END__"))
4735         {
4736             hd.pub.restriction_types = i;
4737             break;
4738         }
4739         hd.restriction[i] = (NV_CHAR *) calloc (strlen((char*)buf) + 1,
4740                                                 sizeof (NV_CHAR));
4741         strcpy (hd.restriction[i], (NV_CHAR *) buf);
4742     }
4743     free (buf);
4744     fseek (fp, utemp + hd.max_restriction_types * hd.restriction_size,
4745            SEEK_SET);
4746 
4747 
4748 
4749     /*  Skip pedigrees. */
4750     if (hd.pub.major_rev < 2)
4751         fseek (fp, hd.pedigree_size * NINT (pow (2.0, (NV_FLOAT64) hd.pedigree_bits)), SEEK_CUR);
4752     hd.pub.pedigree_types = 1;
4753 
4754 
4755 
4756     /*  Read tzfiles.  */
4757 
4758     utemp = ftell (fp);
4759     hd.tzfile = (NV_CHAR **) calloc (hd.max_tzfiles, sizeof (NV_CHAR *));
4760 
4761     if ((buf = (NV_U_BYTE *) calloc (hd.tzfile_size, sizeof (NV_U_BYTE))) ==
4762             NULL)
4763     {
4764         perror ("Allocating tzfile read buffer");
4765         exit (-1);
4766     }
4767 
4768     hd.pub.tzfiles = 0;
4769     for (i = 0 ; i < hd.max_tzfiles ; ++i)
4770     {
4771         chk_fread (buf, hd.tzfile_size, 1, fp);
4772         if (!strcmp ((char*)buf, "__END__"))
4773         {
4774             hd.pub.tzfiles = i;
4775             break;
4776         }
4777         hd.tzfile[i] = (NV_CHAR *) calloc (strlen((char*)buf) + 1, sizeof (NV_CHAR));
4778         strcpy (hd.tzfile[i], (NV_CHAR *) buf);
4779     }
4780     free (buf);
4781     fseek (fp, utemp + hd.max_tzfiles * hd.tzfile_size, SEEK_SET);
4782 
4783 
4784     /*  Read countries.  */
4785 
4786     utemp = ftell (fp);
4787     hd.country = (NV_CHAR **) calloc (hd.max_countries, sizeof (NV_CHAR *));
4788 
4789     if ((buf = (NV_U_BYTE *) calloc (hd.country_size, sizeof (NV_U_BYTE))) ==
4790             NULL)
4791     {
4792         perror ("Allocating country read buffer");
4793         exit (-1);
4794     }
4795 
4796     hd.pub.countries = 0;
4797     for (i = 0 ; i < hd.max_countries ; ++i)
4798     {
4799         chk_fread (buf, hd.country_size, 1, fp);
4800         if (!strcmp ((char*)buf, "__END__"))
4801         {
4802             hd.pub.countries = i;
4803             break;
4804         }
4805         hd.country[i] = (NV_CHAR *) calloc (strlen((char*)buf) + 1,
4806                                             sizeof (NV_CHAR));
4807         strcpy (hd.country[i], (NV_CHAR *) buf);
4808     }
4809     free (buf);
4810     fseek (fp, utemp + hd.max_countries * hd.country_size, SEEK_SET);
4811 
4812 
4813     /*  Read datums.  */
4814 
4815     utemp = ftell (fp);
4816     hd.datum = (NV_CHAR **) calloc (hd.max_datum_types, sizeof (NV_CHAR *));
4817 
4818     if ((buf = (NV_U_BYTE *) calloc (hd.datum_size, sizeof (NV_U_BYTE))) ==
4819             NULL)
4820     {
4821         perror ("Allocating datum read buffer");
4822         exit (-1);
4823     }
4824 
4825     hd.pub.datum_types = 0;
4826     for (i = 0 ; i < hd.max_datum_types ; ++i)
4827     {
4828         chk_fread (buf, hd.datum_size, 1, fp);
4829         if (!strcmp ((char*)buf, "__END__"))
4830         {
4831             hd.pub.datum_types = i;
4832             break;
4833         }
4834         hd.datum[i] = (NV_CHAR *) calloc (strlen((char*)buf) + 1, sizeof (NV_CHAR));
4835         strcpy (hd.datum[i], (NV_CHAR *) buf);
4836     }
4837     free (buf);
4838     fseek (fp, utemp + hd.max_datum_types * hd.datum_size, SEEK_SET);
4839 
4840 
4841 
4842     /*  Read legaleses.  */
4843 
4844     if (hd.pub.major_rev < 2) {
4845         hd.legalese = (NV_CHAR **) malloc (sizeof (NV_CHAR *));
4846         assert (hd.legalese != NULL);
4847         hd.legalese[0] = (NV_CHAR *) malloc (5 * sizeof (NV_CHAR));
4848         assert (hd.legalese[0] != NULL);
4849         strcpy (hd.legalese[0], "NULL");
4850         hd.pub.legaleses = 1;
4851     } else {
4852         utemp = ftell (fp);
4853         hd.legalese = (NV_CHAR **) calloc (hd.max_legaleses, sizeof (NV_CHAR *));
4854 
4855         if ((buf = (NV_U_BYTE *) calloc (hd.legalese_size, sizeof (NV_U_BYTE))) ==
4856                 NULL)
4857         {
4858             perror ("Allocating legalese read buffer");
4859             exit (-1);
4860         }
4861 
4862         hd.pub.legaleses = 0;
4863         for (i = 0 ; i < hd.max_legaleses ; ++i)
4864         {
4865             chk_fread (buf, hd.legalese_size, 1, fp);
4866             if (!strcmp ((char*)buf, "__END__"))
4867             {
4868                 hd.pub.legaleses = i;
4869                 break;
4870             }
4871             hd.legalese[i] = (NV_CHAR *) calloc (strlen((char*)buf) + 1, sizeof (NV_CHAR));
4872             strcpy (hd.legalese[i], (NV_CHAR *) buf);
4873         }
4874         free (buf);
4875         fseek (fp, utemp + hd.max_legaleses * hd.legalese_size, SEEK_SET);
4876     }
4877 
4878 
4879 
4880     /*  Read constituent names.  */
4881 
4882     hd.constituent =
4883         (NV_CHAR **) calloc (hd.pub.constituents, sizeof (NV_CHAR *));
4884 
4885     if ((buf = (NV_U_BYTE *) calloc (hd.constituent_size,
4886                                      sizeof (NV_U_BYTE))) == NULL)
4887     {
4888         perror ("Allocating constituent read buffer");
4889         exit (-1);
4890     }
4891 
4892     for (i = 0 ; i < hd.pub.constituents ; ++i)
4893     {
4894         chk_fread (buf, hd.constituent_size, 1, fp);
4895         hd.constituent[i] = (NV_CHAR *) calloc (strlen((char*)buf) + 1,
4896                                                 sizeof (NV_CHAR));
4897         strcpy (hd.constituent[i], (NV_CHAR *) buf);
4898     }
4899     free (buf);
4900 
4901 
4902     if (hd.speed_offset < 0 || hd.equilibrium_offset < 0 ||
4903             hd.node_offset < 0) {
4904         LOG_ERROR ("libtcd WARNING:  File: %s\n", filename);
4905         LOG_ERROR ("WARNING:  This TCD file was created by a pre-version-1.11 libtcd.\n\
4906 Versions of libtcd prior to 1.11 contained a serious bug that can result\n\
4907 in overflows in the speeds, equilibrium arguments, or node factors.  This\n\
4908 database should be rebuilt from the original data if possible.\n");
4909     }
4910 
4911 
4912     /*  NOTE: Using bit_unpack to get integers.  */
4913 
4914     /*  Read speeds.  */
4915 
4916     hd.speed = (NV_FLOAT64 *) calloc (hd.pub.constituents,
4917                                       sizeof (NV_FLOAT64));
4918 
4919     pos = 0;
4920     /* wasted byte bug in V1 */
4921     if (hd.pub.major_rev < 2)
4922         size = ((hd.pub.constituents * hd.speed_bits) / 8) + 1;
4923     else
4924         size = bits2bytes (hd.pub.constituents * hd.speed_bits);
4925 
4926     if ((buf = (NV_U_BYTE *) calloc (size, sizeof (NV_U_BYTE))) == NULL)
4927     {
4928         perror ("Allocating speed read buffer");
4929         exit (-1);
4930     }
4931 
4932     chk_fread (buf, size, 1, fp);
4933 
4934     for (i = 0 ; i < hd.pub.constituents ; ++i)
4935     {
4936         temp_int = bit_unpack (buf, pos, hd.speed_bits);
4937         hd.speed[i] = (NV_FLOAT64) (temp_int + hd.speed_offset) /
4938                       hd.speed_scale;
4939         pos += hd.speed_bits;
4940         assert (hd.speed[i] >= 0.0);
4941     }
4942     free (buf);
4943 
4944 
4945 
4946     /*  Read equilibrium arguments.  */
4947 
4948     hd.equilibrium = (NV_FLOAT32 **) calloc (hd.pub.constituents,
4949                      sizeof (NV_FLOAT32 *));
4950 
4951     for (i = 0 ; i < hd.pub.constituents ; ++i)
4952     {
4953         hd.equilibrium[i] = (NV_FLOAT32 *) calloc (hd.pub.number_of_years,
4954                             sizeof (NV_FLOAT32));
4955     }
4956 
4957 
4958 
4959     pos = 0;
4960     /* wasted byte bug in V1 */
4961     if (hd.pub.major_rev < 2)
4962         size = ((hd.pub.constituents * hd.pub.number_of_years *
4963                  hd.equilibrium_bits) / 8) + 1;
4964     else
4965         size = bits2bytes (hd.pub.constituents * hd.pub.number_of_years *
4966                            hd.equilibrium_bits);
4967 
4968 
4969     if ((buf = (NV_U_BYTE *) calloc (size, sizeof (NV_U_BYTE))) == NULL)
4970     {
4971         perror ("Allocating equilibrium read buffer");
4972         exit (-1);
4973     }
4974 
4975     chk_fread (buf, size, 1, fp);
4976 
4977     for (i = 0 ; i < hd.pub.constituents ; ++i)
4978     {
4979         for (j = 0 ; j < hd.pub.number_of_years ; ++j)
4980         {
4981             temp_int = bit_unpack (buf, pos, hd.equilibrium_bits);
4982             hd.equilibrium[i][j] = (NV_FLOAT32) (temp_int +
4983                                                  hd.equilibrium_offset) / hd.equilibrium_scale;
4984             pos += hd.equilibrium_bits;
4985         }
4986     }
4987     free (buf);
4988 
4989 
4990 
4991     /*  Read node factors.  */
4992 
4993     hd.node_factor = (NV_FLOAT32 **) calloc (hd.pub.constituents,
4994                      sizeof (NV_FLOAT32 *));
4995 
4996     for (i = 0 ; i < hd.pub.constituents ; ++i)
4997     {
4998         hd.node_factor[i] =
4999             (NV_FLOAT32 *) calloc (hd.pub.number_of_years,
5000                                    sizeof (NV_FLOAT32));
5001     }
5002 
5003 
5004     pos = 0;
5005     /* wasted byte bug in V1 */
5006     if (hd.pub.major_rev < 2)
5007         size = ((hd.pub.constituents * hd.pub.number_of_years *
5008                  hd.node_bits) / 8) + 1;
5009     else
5010         size = bits2bytes (hd.pub.constituents * hd.pub.number_of_years *
5011                            hd.node_bits);
5012 
5013 
5014     if ((buf = (NV_U_BYTE *) calloc (size, sizeof (NV_U_BYTE))) == NULL)
5015     {
5016         perror ("Allocating node read buffer");
5017         exit (-1);
5018     }
5019 
5020     chk_fread (buf, size, 1, fp);
5021 
5022     for (i = 0 ; i < hd.pub.constituents ; ++i)
5023     {
5024         for (j = 0 ; j < hd.pub.number_of_years ; ++j)
5025         {
5026             temp_int = bit_unpack (buf, pos, hd.node_bits);
5027             hd.node_factor[i][j] = (NV_FLOAT32) (temp_int +
5028                                                  hd.node_offset) / hd.node_scale;
5029             pos += hd.node_bits;
5030             assert (hd.node_factor[i][j] > 0.0);
5031         }
5032     }
5033     free (buf);
5034 
5035 
5036     /*  Read the header portion of all of the records in the file and save
5037         the record size, address, and name.  */
5038 
5039     /* DWF added test for zero 2003-11-16 -- happens on create new db */
5040     if (hd.pub.number_of_records) {
5041         if ((tindex = (TIDE_INDEX *) calloc (hd.pub.number_of_records,
5042                                              sizeof (TIDE_INDEX))) == NULL) {
5043             perror ("Allocating tide index");
5044             exit (-1);
5045         }
5046         /*  Set the first address to be immediately after the header  */
5047         tindex[0].address = ftell (fp);
5048     } else tindex = NULL; /* May as well be explicit... */
5049 
5050     for (i = 0 ; i < hd.pub.number_of_records ; ++i)
5051     {
5052         /*  Set the address for the next record so that
5053             read_partial_tide_record will know where to go.  */
5054 
5055         if (i) tindex[i].address = tindex[i - 1].address +
5056                                        rec.header.record_size;
5057 
5058         read_partial_tide_record (i, &rec);
5059 
5060 
5061         /*  Save the header info in the index.  */
5062 
5063         tindex[i].record_size = rec.header.record_size;
5064         tindex[i].record_type = rec.header.record_type;
5065         tindex[i].reference_station = rec.header.reference_station;
5066         assert (rec.header.tzfile >= 0);
5067         tindex[i].tzfile = rec.header.tzfile;
5068         tindex[i].lat = NINT (rec.header.latitude * hd.latitude_scale);
5069         tindex[i].lon = NINT (rec.header.longitude * hd.longitude_scale);
5070 
5071         if ((tindex[i].name =
5072                     (NV_CHAR *) calloc (strlen (rec.header.name) + 1,
5073                                         sizeof (NV_CHAR))) == NULL)
5074         {
5075             perror ("Allocating index name memory");
5076             exit (-1);
5077         }
5078 
5079         strcpy (tindex[i].name, rec.header.name);
5080     }
5081 
5082 
5083     current_record = -1;
5084     current_index = -1;
5085 
5086     return (NVTrue);
5087 }
5088 
5089 
5090 /*****************************************************************************\
5091 
5092     Function        open_tide_db - opens the tide database
5093 
5094     Synopsis        open_tide_db (file);
5095 
5096                     NV_CHAR *file           database file name
5097 
5098     Returns         NV_BOOL                 NVTrue if file opened
5099 
5100     Author          Jan C. Depner
5101     Date            08/01/02
5102 
5103     See libtcd.html for changelog.
5104 
5105 \*****************************************************************************/
5106 
open_tide_db(const NV_CHAR * file)5107 NV_BOOL open_tide_db (const NV_CHAR *file)
5108 {
5109     assert (file);
5110     current_record = -1;
5111     current_index = -1;
5112     if (fp) {
5113         if (!strcmp(file,filename) && !modified) return NVTrue;
5114         else close_tide_db();
5115     }
5116     if ((fp = fopen (file, "rb+")) == NULL) {
5117         if ((fp = fopen (file, "rb")) == NULL) return (NVFalse);
5118     }
5119     boundscheck_monologue (file);
5120     strcpy (filename, file);
5121     return (read_tide_db_header());
5122 }
5123 
5124 
5125 /*****************************************************************************\
5126 
5127     Function        close_tide_db - closes the tide database
5128 
5129     Synopsis        close_tide_db ();
5130 
5131     Returns         void
5132 
5133     Author          Jan C. Depner
5134     Date            08/01/02
5135 
5136     See libtcd.html for changelog.
5137 
5138     If the global modified flag is true, the database header is rewritten
5139     before the database is closed.  The modified flag is then cleared.
5140 
5141 \*****************************************************************************/
5142 
close_tide_db()5143 void close_tide_db ()
5144 {
5145     NV_U_INT32 i;
5146 
5147     if (!fp) {
5148         LOG_ERROR ("libtcd warning: close_tide_db called when no database open\n");
5149         return;
5150     }
5151 
5152     /*  If we've changed something in the file, write the header to reset
5153         the last modified time.  */
5154 
5155     if (modified) write_tide_db_header ();
5156 
5157 
5158     /*  Free all of the temporary memory.  */
5159 
5160     assert (hd.constituent);
5161     for (i = 0 ; i < hd.pub.constituents ; ++i)
5162     {
5163         if (hd.constituent[i] != NULL) free (hd.constituent[i]);
5164     }
5165     free (hd.constituent);
5166     hd.constituent = NULL;
5167 
5168     if (hd.speed != NULL) free (hd.speed);
5169 
5170     assert (hd.equilibrium);
5171     for (i = 0 ; i < hd.pub.constituents ; ++i)
5172     {
5173         if (hd.equilibrium[i] != NULL) free (hd.equilibrium[i]);
5174     }
5175     free (hd.equilibrium);
5176     hd.equilibrium = NULL;
5177 
5178     assert (hd.node_factor);
5179     for (i = 0 ; i < hd.pub.constituents ; ++i)
5180     {
5181         if (hd.node_factor[i] != NULL) free (hd.node_factor[i]);
5182     }
5183     free (hd.node_factor);
5184     hd.node_factor = NULL;
5185 
5186     assert (hd.level_unit);
5187     for (i = 0 ; i < hd.pub.level_unit_types ; ++i)
5188     {
5189         if (hd.level_unit[i] != NULL) free (hd.level_unit[i]);
5190     }
5191     free (hd.level_unit);
5192     hd.level_unit = NULL;
5193 
5194     assert (hd.dir_unit);
5195     for (i = 0 ; i < hd.pub.dir_unit_types ; ++i)
5196     {
5197         if (hd.dir_unit[i] != NULL) free (hd.dir_unit[i]);
5198     }
5199     free (hd.dir_unit);
5200     hd.dir_unit = NULL;
5201 
5202     assert (hd.restriction);
5203     for (i = 0 ; i < hd.max_restriction_types ; ++i)
5204     {
5205         if (hd.restriction[i] != NULL) free (hd.restriction[i]);
5206     }
5207     free (hd.restriction);
5208     hd.restriction = NULL;
5209 
5210     assert (hd.legalese);
5211     for (i = 0 ; i < hd.max_legaleses ; ++i)
5212     {
5213         if (hd.legalese[i] != NULL) free (hd.legalese[i]);
5214     }
5215     free (hd.legalese);
5216     hd.legalese = NULL;
5217 
5218     assert (hd.tzfile);
5219     for (i = 0 ; i < hd.max_tzfiles ; ++i)
5220     {
5221         if (hd.tzfile[i] != NULL) free (hd.tzfile[i]);
5222     }
5223     free (hd.tzfile);
5224     hd.tzfile = NULL;
5225 
5226     assert (hd.country);
5227     for (i = 0 ; i < hd.max_countries ; ++i)
5228     {
5229         if (hd.country[i] != NULL) free (hd.country[i]);
5230     }
5231     free (hd.country);
5232     hd.country = NULL;
5233 
5234     assert (hd.datum);
5235     for (i = 0 ; i < hd.max_datum_types ; ++i)
5236     {
5237         if (hd.datum[i] != NULL) free (hd.datum[i]);
5238     }
5239     free (hd.datum);
5240     hd.datum = NULL;
5241 
5242     /* tindex will still be null on create_tide_db */
5243     if (tindex) {
5244         for (i = 0 ; i < hd.pub.number_of_records ; ++i)
5245         {
5246             if (tindex[i].name) free (tindex[i].name);
5247         }
5248         free (tindex);
5249         tindex = NULL;
5250     }
5251 
5252     fclose (fp);
5253     fp = NULL;
5254     modified = NVFalse;
5255 
5256     /* Don't nullify the filename; there are places in the code where
5257        open_tide_db (filename) is invoked after close_tide_db().  This
5258        does not break the cache logic in open_tide_db because tindex
5259        is still nullified. */
5260 }
5261 
5262 
5263 /*****************************************************************************\
5264 
5265     Function        create_tide_db - creates the tide database
5266 
5267     Synopsis        create_tide_db (file, constituents, constituent, speed,
5268                         start_year, num_years, equilibrium, node_factor);
5269 
5270                     NV_CHAR *file              database file name
5271                     NV_U_INT32 constituents    number of constituents
5272                     NV_CHAR *constituent[]     constituent names
5273                     NV_FLOAT64 *speed          speed values
5274                     NV_INT32 start_year        start year
5275                     NV_U_INT32 num_years       number of years
5276                     NV_FLOAT32 *equilibrium[]  equilibrium arguments
5277                     NV_FLOAT32 *node_factor[]  node factors
5278 
5279     Returns         NV_BOOL                 NVTrue if file created
5280 
5281     Author          Jan C. Depner
5282     Date            08/01/02
5283 
5284     See libtcd.html for changelog.
5285 
5286 \*****************************************************************************/
5287 
create_tide_db(const NV_CHAR * file,NV_U_INT32 constituents,NV_CHAR const * const constituent[],const NV_FLOAT64 * speed,NV_INT32 start_year,NV_U_INT32 num_years,NV_FLOAT32 const * const equilibrium[],NV_FLOAT32 const * const node_factor[])5288 NV_BOOL create_tide_db (const NV_CHAR *file, NV_U_INT32 constituents, NV_CHAR
5289                         const * const constituent[], const NV_FLOAT64 *speed, NV_INT32 start_year,
5290                         NV_U_INT32 num_years, NV_FLOAT32 const * const equilibrium[], NV_FLOAT32
5291                         const * const node_factor[])
5292 {
5293     NV_U_INT32            i, j;
5294     NV_FLOAT64            min_value, max_value;
5295     NV_INT32              temp_int;
5296 
5297     /* Validate input */
5298     assert (file);
5299     assert (constituent);
5300     assert (speed);
5301     assert (equilibrium);
5302     assert (node_factor);
5303     for (i = 0 ; i < constituents ; ++i) {
5304         if (speed[i] < 0.0) {
5305             LOG_ERROR ("libtcd create_tide_db: somebody tried to set a negative speed (%f)\n", speed[i]);
5306             return NVFalse;
5307         }
5308         for (j = 0 ; j < num_years ; ++j) {
5309             if (node_factor[i][j] <= 0.0) {
5310                 LOG_ERROR ("libtcd create_tide_db: somebody tried to set a negative or zero node factor (%f)\n", node_factor[i][j]);
5311                 return NVFalse;
5312             }
5313         }
5314     }
5315 
5316     if (fp)
5317         close_tide_db();
5318 
5319     if ((fp = fopen (file, "wb+")) == NULL) {
5320         perror (file);
5321         return (NVFalse);
5322     }
5323 
5324     /*  Zero out the header structure.  */
5325 
5326     memset (&hd, 0, sizeof (hd));
5327 
5328     hd.pub.major_rev = LIBTCD_MAJOR_REV;
5329     hd.pub.minor_rev = LIBTCD_MINOR_REV;
5330 
5331     hd.header_size = DEFAULT_HEADER_SIZE;
5332     hd.pub.number_of_records = DEFAULT_NUMBER_OF_RECORDS;
5333 
5334     hd.pub.start_year = start_year;
5335     hd.pub.number_of_years = num_years;
5336 
5337     hd.pub.constituents = constituents;
5338 
5339 
5340     /*  Constituent names.  */
5341 
5342     hd.constituent =
5343         (NV_CHAR **) calloc (hd.pub.constituents, sizeof (NV_CHAR *));
5344     for (i = 0 ; i < hd.pub.constituents ; ++i)
5345     {
5346         hd.constituent[i] = (NV_CHAR *) calloc (strlen (constituent[i]) + 1,
5347                                                 sizeof (NV_CHAR));
5348         strcpy (hd.constituent[i], constituent[i]);
5349     }
5350 
5351 
5352     /* A constituent count is stored with each reference station record,
5353        and it uses constituent_bits, so we need to be able to store
5354        the count itself (not just the values 0..count-1). */
5355     hd.constituent_bits = calculate_bits (hd.pub.constituents);
5356 
5357 
5358     /*  Set all of the speed attributes.  */
5359 
5360     hd.speed =  (NV_FLOAT64 *) calloc (hd.pub.constituents,
5361                                        sizeof (NV_FLOAT64));
5362 
5363     hd.speed_scale = DEFAULT_SPEED_SCALE;
5364     min_value = 99999999.0;
5365     max_value = -99999999.0;
5366     for (i = 0 ; i < hd.pub.constituents ; ++i)
5367     {
5368         if (speed[i] < min_value) min_value = speed[i];
5369         if (speed[i] > max_value) max_value = speed[i];
5370 
5371         hd.speed[i] = speed[i];
5372     }
5373 
5374     /* DWF fixed sign reversal 2003-11-16 */
5375     /* DWF harmonized rounding with the way it is done in write_tide_db_header
5376        2007-01-22 */
5377     hd.speed_offset = (NINT (min_value * hd.speed_scale));
5378     temp_int = NINT (max_value * hd.speed_scale) - hd.speed_offset;
5379     assert (temp_int >= 0);
5380     hd.speed_bits = calculate_bits ((NV_U_INT32)temp_int);
5381     /* Generally 31.  With signed ints we don't have any bits to spare. */
5382     assert (hd.speed_bits < 32);
5383 
5384     /*  Set all of the equilibrium attributes.  */
5385 
5386     hd.equilibrium = (NV_FLOAT32 **) calloc (hd.pub.constituents,
5387                      sizeof (NV_FLOAT32 *));
5388 
5389     hd.equilibrium_scale = DEFAULT_EQUILIBRIUM_SCALE;
5390     min_value = 99999999.0;
5391     max_value = -99999999.0;
5392     for (i = 0 ; i < hd.pub.constituents ; ++i)
5393     {
5394         hd.equilibrium[i] = (NV_FLOAT32 *) calloc (hd.pub.number_of_years,
5395                             sizeof (NV_FLOAT32));
5396         for (j = 0 ; j < hd.pub.number_of_years ; ++j)
5397         {
5398             if (equilibrium[i][j] < min_value) min_value = equilibrium[i][j];
5399             if (equilibrium[i][j] > max_value) max_value = equilibrium[i][j];
5400 
5401             hd.equilibrium[i][j] = equilibrium[i][j];
5402         }
5403     }
5404 
5405     /* DWF fixed sign reversal 2003-11-16 */
5406     /* DWF harmonized rounding with the way it is done in write_tide_db_header
5407        2007-01-22 */
5408     hd.equilibrium_offset = (NINT (min_value * hd.equilibrium_scale));
5409     temp_int = NINT (max_value * hd.equilibrium_scale) - hd.equilibrium_offset;
5410     assert (temp_int >= 0);
5411     hd.equilibrium_bits = calculate_bits ((NV_U_INT32)temp_int);
5412 
5413 
5414     /*  Set all of the node factor attributes.  */
5415 
5416     hd.node_factor = (NV_FLOAT32 **) calloc (hd.pub.constituents,
5417                      sizeof (NV_FLOAT32 *));
5418 
5419     hd.node_scale = DEFAULT_NODE_SCALE;
5420     min_value = 99999999.0;
5421     max_value = -99999999.0;
5422     for (i = 0 ; i < hd.pub.constituents ; ++i)
5423     {
5424         hd.node_factor[i] = (NV_FLOAT32 *) calloc (hd.pub.number_of_years,
5425                             sizeof (NV_FLOAT32));
5426         for (j = 0 ; j < hd.pub.number_of_years ; ++j)
5427         {
5428             if (node_factor[i][j] < min_value) min_value =
5429                     node_factor[i][j];
5430             if (node_factor[i][j] > max_value) max_value =
5431                     node_factor[i][j];
5432 
5433             hd.node_factor[i][j] = node_factor[i][j];
5434         }
5435     }
5436 
5437     /* DWF fixed sign reversal 2003-11-16 */
5438     /* DWF harmonized rounding with the way it is done in write_tide_db_header
5439        2007-01-22 */
5440     hd.node_offset = (NINT (min_value * hd.node_scale));
5441     temp_int = NINT (max_value * hd.node_scale) - hd.node_offset;
5442     assert (temp_int >= 0);
5443     hd.node_bits = calculate_bits ((NV_U_INT32)temp_int);
5444 
5445 
5446     /*  Default city.  */
5447 
5448     hd.amplitude_bits = DEFAULT_AMPLITUDE_BITS;
5449     hd.amplitude_scale = DEFAULT_AMPLITUDE_SCALE;
5450     hd.epoch_bits = DEFAULT_EPOCH_BITS;
5451     hd.epoch_scale = DEFAULT_EPOCH_SCALE;
5452 
5453     hd.record_type_bits = DEFAULT_RECORD_TYPE_BITS;
5454     hd.latitude_bits = DEFAULT_LATITUDE_BITS;
5455     hd.latitude_scale = DEFAULT_LATITUDE_SCALE;
5456     hd.longitude_bits = DEFAULT_LONGITUDE_BITS;
5457     hd.longitude_scale = DEFAULT_LONGITUDE_SCALE;
5458     hd.record_size_bits = DEFAULT_RECORD_SIZE_BITS;
5459 
5460     hd.station_bits = DEFAULT_STATION_BITS;
5461 
5462     hd.datum_offset_bits = DEFAULT_DATUM_OFFSET_BITS;
5463     hd.datum_offset_scale = DEFAULT_DATUM_OFFSET_SCALE;
5464     hd.date_bits = DEFAULT_DATE_BITS;
5465     hd.months_on_station_bits = DEFAULT_MONTHS_ON_STATION_BITS;
5466     hd.confidence_value_bits = DEFAULT_CONFIDENCE_VALUE_BITS;
5467 
5468     hd.time_bits = DEFAULT_TIME_BITS;
5469     hd.level_add_bits = DEFAULT_LEVEL_ADD_BITS;
5470     hd.level_add_scale = DEFAULT_LEVEL_ADD_SCALE;
5471     hd.level_multiply_bits = DEFAULT_LEVEL_MULTIPLY_BITS;
5472     hd.level_multiply_scale = DEFAULT_LEVEL_MULTIPLY_SCALE;
5473     hd.direction_bits = DEFAULT_DIRECTION_BITS;
5474 
5475     hd.constituent_size = DEFAULT_CONSTITUENT_SIZE;
5476     hd.level_unit_size = DEFAULT_LEVEL_UNIT_SIZE;
5477     hd.dir_unit_size = DEFAULT_DIR_UNIT_SIZE;
5478     hd.restriction_size = DEFAULT_RESTRICTION_SIZE;
5479     hd.tzfile_size = DEFAULT_TZFILE_SIZE;
5480     hd.country_size = DEFAULT_COUNTRY_SIZE;
5481     hd.datum_size = DEFAULT_DATUM_SIZE;
5482     hd.legalese_size = DEFAULT_LEGALESE_SIZE;
5483 
5484 
5485 
5486     /*  Level units.  */
5487 
5488     hd.pub.level_unit_types = DEFAULT_LEVEL_UNIT_TYPES;
5489     hd.level_unit_bits = calculate_bits (hd.pub.level_unit_types - 1);
5490 
5491     hd.level_unit = (NV_CHAR **) calloc (hd.pub.level_unit_types,
5492                                          sizeof (NV_CHAR *));
5493     for (i = 0 ; i < hd.pub.level_unit_types ; ++i)
5494     {
5495         hd.level_unit[i] = (NV_CHAR *) calloc (strlen (level_unit[i]) + 1,
5496                                                sizeof (NV_CHAR));
5497         strcpy (hd.level_unit[i], level_unit[i]);
5498     }
5499 
5500 
5501     /*  Direction units.  */
5502 
5503     hd.pub.dir_unit_types = DEFAULT_DIR_UNIT_TYPES;
5504     hd.dir_unit_bits = calculate_bits (hd.pub.dir_unit_types - 1);
5505 
5506     hd.dir_unit = (NV_CHAR **) calloc (hd.pub.dir_unit_types,
5507                                        sizeof (NV_CHAR *));
5508     for (i = 0 ; i < hd.pub.dir_unit_types ; ++i)
5509     {
5510         hd.dir_unit[i] = (NV_CHAR *) calloc (strlen (dir_unit[i]) + 1,
5511                                              sizeof (NV_CHAR));
5512         strcpy (hd.dir_unit[i], dir_unit[i]);
5513     }
5514 
5515 
5516     /*  Restrictions.  */
5517 
5518     hd.restriction_bits = DEFAULT_RESTRICTION_BITS;
5519     hd.max_restriction_types = NINT (pow (2.0,
5520                                           (NV_FLOAT64) hd.restriction_bits));
5521     hd.pub.restriction_types = DEFAULT_RESTRICTION_TYPES;
5522 
5523     hd.restriction = (NV_CHAR **) calloc (hd.max_restriction_types,
5524                                           sizeof (NV_CHAR *));
5525     for (i = 0 ; i < hd.max_restriction_types ; ++i)
5526     {
5527         if (i == hd.pub.restriction_types) break;
5528 
5529         hd.restriction[i] = (NV_CHAR *) calloc (strlen (restriction[i]) + 1,
5530                                                 sizeof (NV_CHAR));
5531         strcpy (hd.restriction[i], restriction[i]);
5532     }
5533 
5534 
5535     /*  Legaleses.  */
5536 
5537     hd.legalese_bits = DEFAULT_LEGALESE_BITS;
5538     hd.max_legaleses = NINT (pow (2.0, (NV_FLOAT64) hd.legalese_bits));
5539     hd.pub.legaleses = DEFAULT_LEGALESES;
5540 
5541     hd.legalese = (NV_CHAR **) calloc (hd.max_legaleses,
5542                                        sizeof (NV_CHAR *));
5543     for (i = 0 ; i < hd.max_legaleses ; ++i)
5544     {
5545         if (i == hd.pub.legaleses) break;
5546 
5547         hd.legalese[i] = (NV_CHAR *) calloc (strlen (legalese[i]) + 1,
5548                                              sizeof (NV_CHAR));
5549         strcpy (hd.legalese[i], legalese[i]);
5550     }
5551 
5552 
5553     /*  Tzfiles.  */
5554 
5555     hd.tzfile_bits = DEFAULT_TZFILE_BITS;
5556     hd.max_tzfiles = NINT (pow (2.0, (NV_FLOAT64) hd.tzfile_bits));
5557     hd.pub.tzfiles = DEFAULT_TZFILES;
5558 
5559     hd.tzfile = (NV_CHAR **) calloc (hd.max_tzfiles, sizeof (NV_CHAR *));
5560     for (i = 0 ; i < hd.max_tzfiles ; ++i)
5561     {
5562         if (i == hd.pub.tzfiles) break;
5563 
5564         hd.tzfile[i] = (NV_CHAR *) calloc (strlen (tzfile[i]) + 1,
5565                                            sizeof (NV_CHAR));
5566         strcpy (hd.tzfile[i], tzfile[i]);
5567     }
5568 
5569 
5570     /*  Countries.  */
5571 
5572     hd.country_bits = DEFAULT_COUNTRY_BITS;
5573     hd.max_countries = NINT (pow (2.0, (NV_FLOAT64) hd.country_bits));
5574     hd.pub.countries = DEFAULT_COUNTRIES;
5575 
5576     hd.country = (NV_CHAR **) calloc (hd.max_countries, sizeof (NV_CHAR *));
5577     for (i = 0 ; i < hd.max_countries ; ++i)
5578     {
5579         if (i == hd.pub.countries) break;
5580 
5581         hd.country[i] = (NV_CHAR *) calloc (strlen (country[i]) + 1,
5582                                             sizeof (NV_CHAR));
5583         strcpy (hd.country[i], country[i]);
5584     }
5585 
5586 
5587     /*  Datums.  */
5588 
5589     hd.datum_bits = DEFAULT_DATUM_BITS;
5590     hd.max_datum_types = NINT (pow (2.0, (NV_FLOAT64) hd.datum_bits));
5591     hd.pub.datum_types = DEFAULT_DATUM_TYPES;
5592 
5593     hd.datum = (NV_CHAR **) calloc (hd.max_datum_types, sizeof (NV_CHAR *));
5594     for (i = 0 ; i < hd.max_datum_types ; ++i)
5595     {
5596         if (i == hd.pub.datum_types) break;
5597 
5598         hd.datum[i] = (NV_CHAR *) calloc (strlen (datum[i]) + 1,
5599                                           sizeof (NV_CHAR));
5600         strcpy (hd.datum[i], datum[i]);
5601     }
5602 
5603 
5604     /*  Write the header to the file and close. */
5605 
5606     modified = NVTrue;
5607     close_tide_db ();
5608 
5609 
5610     /*  Re-open it and read the header from the file.  */
5611 
5612     i = (open_tide_db (file));
5613 
5614 
5615     /*  Set the correct end of file position since the one in the header is
5616         set to 0.  */
5617     hd.end_of_file = ftell(fp);
5618     /* DWF 2004-08-15: if the original program exits without adding any
5619        records, that doesn't help!  Rewrite the header with correct
5620        end_of_file. */
5621     write_tide_db_header ();
5622 
5623     return (i);
5624 }
5625 
5626 
5627 /*****************************************************************************\
5628   DWF 2004-10-13
5629   Used in check_tide_record.
5630 \*****************************************************************************/
check_date(NV_U_INT32 date)5631 static NV_BOOL check_date (NV_U_INT32 date) {
5632     if (date) {
5633         unsigned m, d;
5634         date %= 10000;
5635         m = date / 100;
5636         d = date % 100;
5637         if (m < 1 || m > 12 || d < 1 || d > 31)
5638             return NVFalse;
5639     }
5640     return NVTrue;
5641 }
5642 
5643 
5644 /*****************************************************************************\
5645   DWF 2004-10-13
5646   Returns true iff a record is valid enough to write.  Reports all problems
5647   to LOG_ERROR.  The checks are not designed to be airtight (e.g., if you
5648   use 360 degrees instead of 0 we'll let it slide).
5649 
5650   Mild side effects may occur:
5651   Note that the units-to-level-units COMPAT114 trick is wedged in here.
5652 \*****************************************************************************/
check_tide_record(TIDE_RECORD * rec)5653 static NV_BOOL check_tide_record (TIDE_RECORD *rec) {
5654     NV_U_INT32 i;
5655     NV_BOOL ret = NVTrue;
5656 
5657     if (!rec) {
5658         LOG_ERROR ("libtcd error: null pointer passed to check_tide_record\n");
5659         return NVFalse;
5660     }
5661 
5662     /* These are all static fields--if a buffer overflow has occurred on one
5663        of these, other fields might be invalid, but the problem started here. */
5664     boundscheck_oneliner (rec->header.name);
5665     boundscheck_oneliner (rec->source);
5666     boundscheck_monologue (rec->comments);
5667     boundscheck_monologue (rec->notes);
5668     boundscheck_oneliner (rec->station_id_context);
5669     boundscheck_oneliner (rec->station_id);
5670     boundscheck_monologue (rec->xfields);
5671 
5672 #ifdef COMPAT114
5673     if (rec->header.record_type == REFERENCE_STATION && rec->units > 0)
5674         rec->level_units = rec->units;
5675 #endif
5676 
5677     if (rec->header.latitude < -90.0 || rec->header.latitude > 90.0 ||
5678             rec->header.longitude < -180.0 || rec->header.longitude > 180.0) {
5679         LOG_ERROR ("libtcd error: bad coordinates in tide record\n");
5680         ret = NVFalse;
5681     }
5682 
5683     if (rec->header.tzfile < 0 || rec->header.tzfile >= (NV_INT32)hd.pub.tzfiles) {
5684         LOG_ERROR ("libtcd error: bad tzfile in tide record\n");
5685         ret = NVFalse;
5686     }
5687 
5688     if (rec->header.name[0] == '\0') {
5689         LOG_ERROR ("libtcd error: null name in tide record\n");
5690         ret = NVFalse;
5691     }
5692 
5693     if (rec->country < 0 || rec->country >= (NV_INT32)hd.pub.countries) {
5694         LOG_ERROR ("libtcd error: bad country in tide record\n");
5695         ret = NVFalse;
5696     }
5697 
5698     if (rec->restriction >= hd.pub.restriction_types) {
5699         LOG_ERROR ("libtcd error: bad restriction in tide record\n");
5700         ret = NVFalse;
5701     }
5702 
5703     if (rec->legalese >= hd.pub.legaleses) {
5704         LOG_ERROR ("libtcd error: bad legalese in tide record\n");
5705         ret = NVFalse;
5706     }
5707 
5708     if (!check_date (rec->date_imported)) {
5709         LOG_ERROR ("libtcd error: bad date_imported in tide record\n");
5710         ret = NVFalse;
5711     }
5712 
5713     if (rec->direction_units >= hd.pub.dir_unit_types) {
5714         LOG_ERROR ("libtcd error: bad direction_units in tide record\n");
5715         ret = NVFalse;
5716     }
5717 
5718     if (rec->min_direction < 0 || rec->min_direction > 361) {
5719         LOG_ERROR ("libtcd error: min_direction out of range in tide record\n");
5720         ret = NVFalse;
5721     }
5722 
5723     if (rec->max_direction < 0 || rec->max_direction > 361) {
5724         LOG_ERROR ("libtcd error: max_direction out of range in tide record\n");
5725         ret = NVFalse;
5726     }
5727 
5728     if (rec->level_units >= hd.pub.level_unit_types) {
5729         LOG_ERROR ("libtcd error: bad units in tide record\n");
5730         ret = NVFalse;
5731     }
5732 
5733     switch (rec->header.record_type) {
5734     case REFERENCE_STATION:
5735         if (rec->header.reference_station != -1) {
5736             LOG_ERROR ("libtcd error: type 1 record, reference_station != -1\n");
5737             ret = NVFalse;
5738         }
5739 
5740         if (rec->datum_offset < -13421.7728 || rec->datum_offset > 13421.7727) {
5741             LOG_ERROR ("libtcd error: datum_offset out of range in tide record\n");
5742             ret = NVFalse;
5743         }
5744 
5745         if (rec->datum < 0 || rec->datum >= (NV_INT32)hd.pub.datum_types) {
5746             LOG_ERROR ("libtcd error: bad datum in tide record\n");
5747             ret = NVFalse;
5748         }
5749 
5750         if (rec->zone_offset < -4096 || rec->zone_offset > 4095 ||
5751                 rec->zone_offset % 100 >= 60) {
5752             LOG_ERROR ("libtcd error: bad zone_offset in tide record\n");
5753             ret = NVFalse;
5754         }
5755 
5756         if (!check_date (rec->expiration_date)) {
5757             LOG_ERROR ("libtcd error: bad expiration_date in tide record\n");
5758             ret = NVFalse;
5759         }
5760 
5761         if (rec->months_on_station > 1023) {
5762             LOG_ERROR ("libtcd error: months_on_station out of range in tide record\n");
5763             ret = NVFalse;
5764         }
5765 
5766         if (!check_date (rec->last_date_on_station)) {
5767             LOG_ERROR ("libtcd error: bad last_date_on_station in tide record\n");
5768             ret = NVFalse;
5769         }
5770 
5771         if (rec->confidence > 15) {
5772             LOG_ERROR ("libtcd error: confidence out of range in tide record\n");
5773             ret = NVFalse;
5774         }
5775 
5776         /* Only issue each error once. */
5777         for (i=0; i < hd.pub.constituents; ++i) {
5778             if (rec->amplitude[i] < 0.0 || rec->amplitude[i] > 52.4287) {
5779                 LOG_ERROR ("libtcd error: constituent amplitude out of range in tide record\n");
5780                 ret = NVFalse;
5781                 break;
5782             }
5783         }
5784         for (i=0; i < hd.pub.constituents; ++i) {
5785             if (rec->epoch[i] < 0.0 || rec->epoch[i] > 360.0) {
5786                 LOG_ERROR ("libtcd error: constituent epoch out of range in tide record\n");
5787                 ret = NVFalse;
5788                 break;
5789             }
5790         }
5791 
5792         break;
5793 
5794     case SUBORDINATE_STATION:
5795         if (rec->header.reference_station < 0 || rec->header.reference_station
5796                 >= (NV_INT32)hd.pub.number_of_records) {
5797             LOG_ERROR ("libtcd error: bad reference_station in tide record\n");
5798             ret = NVFalse;
5799         }
5800 
5801         if (rec->min_time_add < -4096 || rec->min_time_add > 4095 ||
5802                 rec->min_time_add % 100 >= 60) {
5803             LOG_ERROR ("libtcd error: bad min_time_add in tide record\n");
5804             ret = NVFalse;
5805         }
5806 
5807         if (rec->min_level_add < -65.536 || rec->min_level_add > 65.535) {
5808             LOG_ERROR ("libtcd error: min_level_add out of range in tide record\n");
5809             ret = NVFalse;
5810         }
5811 
5812         if (rec->min_level_multiply < 0.0 || rec->min_level_multiply > 65.535) {
5813             LOG_ERROR ("libtcd error: min_level_multiply out of range in tide record\n");
5814             ret = NVFalse;
5815         }
5816 
5817         if (rec->max_time_add < -4096 || rec->max_time_add > 4095 ||
5818                 rec->max_time_add % 100 >= 60) {
5819             LOG_ERROR ("libtcd error: bad max_time_add in tide record\n");
5820             ret = NVFalse;
5821         }
5822 
5823         if (rec->max_level_add < -65.536 || rec->max_level_add > 65.535) {
5824             LOG_ERROR ("libtcd error: max_level_add out of range in tide record\n");
5825             ret = NVFalse;
5826         }
5827 
5828         if (rec->max_level_multiply < 0.0 || rec->max_level_multiply > 65.535) {
5829             LOG_ERROR ("libtcd error: max_level_multiply out of range in tide record\n");
5830             ret = NVFalse;
5831         }
5832 
5833         if (rec->flood_begins != NULLSLACKOFFSET && (rec->flood_begins < -4096 ||
5834                 rec->flood_begins > 4095 || rec->flood_begins % 100 >= 60)) {
5835             LOG_ERROR ("libtcd error: bad flood_begins in tide record\n");
5836             ret = NVFalse;
5837         }
5838 
5839         if (rec->ebb_begins != NULLSLACKOFFSET && (rec->ebb_begins < -4096 ||
5840                 rec->ebb_begins > 4095 || rec->ebb_begins % 100 >= 60)) {
5841             LOG_ERROR ("libtcd error: bad ebb_begins in tide record\n");
5842             ret = NVFalse;
5843         }
5844 
5845         break;
5846 
5847     default:
5848         LOG_ERROR ("libtcd error: invalid record_type in tide record\n");
5849         ret = NVFalse;
5850     }
5851 
5852     if (ret == NVFalse)
5853         dump_tide_record (rec);
5854     return ret;
5855 }
5856 
5857 
5858 /*****************************************************************************\
5859   DWF 2004-10-13
5860   Calculate size of a tide record as it would be encoded in the TCD file.
5861   Size is stored in record_size field.  Return is number of constituents
5862   that will be encoded.
5863 \*****************************************************************************/
figure_size(TIDE_RECORD * rec)5864 static NV_U_INT32 figure_size (TIDE_RECORD *rec) {
5865     NV_U_INT32 i, count=0, name_size, source_size, comments_size,
5866                   notes_size, station_id_context_size, station_id_size, xfields_size;
5867 
5868     assert (rec);
5869 
5870     /*  Figure out how many bits we'll need for this record. */
5871 
5872     name_size = strlen(clip_string(rec->header.name))+1;
5873     source_size = strlen(clip_string(rec->source))+1;
5874     comments_size = strlen(clip_string(rec->comments))+1;
5875     notes_size = strlen(clip_string(rec->notes))+1;
5876     station_id_context_size = strlen(clip_string(rec->station_id_context))+1;
5877     station_id_size = strlen(clip_string(rec->station_id))+1;
5878     /* No clipping on xfields -- trailing \n required by syntax */
5879     xfields_size = strlen(rec->xfields)+1;
5880 
5881     rec->header.record_size =
5882         hd.record_size_bits +
5883         hd.record_type_bits +
5884         hd.latitude_bits +
5885         hd.longitude_bits +
5886         hd.station_bits +
5887         hd.tzfile_bits +
5888         (name_size * 8) +
5889 
5890         hd.country_bits +
5891         (source_size  * 8) +
5892         hd.restriction_bits +
5893         (comments_size * 8) +
5894         (notes_size * 8) +
5895         hd.legalese_bits +
5896         (station_id_context_size * 8) +
5897         (station_id_size * 8) +
5898         hd.date_bits +
5899         (xfields_size * 8) +
5900         hd.dir_unit_bits +
5901         hd.direction_bits +
5902         hd.direction_bits +
5903         hd.level_unit_bits;
5904 
5905     switch (rec->header.record_type) {
5906     case REFERENCE_STATION:
5907         rec->header.record_size +=
5908             hd.datum_offset_bits +
5909             hd.datum_bits +
5910             hd.time_bits +
5911             hd.date_bits +
5912             hd.months_on_station_bits +
5913             hd.date_bits +
5914             hd.confidence_value_bits +
5915             hd.constituent_bits;
5916 
5917         for (i = 0 ; i < hd.pub.constituents ; ++i)
5918         {
5919             assert (rec->amplitude[i] >= 0.0);
5920             if (rec->amplitude[i] >= AMPLITUDE_EPSILON) ++count;
5921         }
5922 
5923         rec->header.record_size +=
5924             (count * hd.constituent_bits +
5925              count * hd.amplitude_bits +
5926              count * hd.epoch_bits);
5927 
5928         break;
5929 
5930     case SUBORDINATE_STATION:
5931         rec->header.record_size +=
5932             hd.time_bits +
5933             hd.level_add_bits +
5934             hd.level_multiply_bits +
5935             hd.time_bits +
5936             hd.level_add_bits +
5937             hd.level_multiply_bits +
5938             hd.time_bits +
5939             hd.time_bits;
5940         break;
5941 
5942     default:
5943         assert (0);
5944     }
5945 
5946     rec->header.record_size = bits2bytes (rec->header.record_size);
5947     return count;
5948 }
5949 
5950 
5951 /*****************************************************************************\
5952 DWF 2004-10-14
5953 \*****************************************************************************/
pack_string(NV_U_BYTE * buf,NV_U_INT32 * pos,NV_CHAR * s)5954 static void pack_string (NV_U_BYTE *buf, NV_U_INT32 *pos, NV_CHAR *s) {
5955     NV_U_INT32 i, temp_size;
5956     assert (buf);
5957     assert (pos);
5958     assert (s);
5959     temp_size = strlen(s)+1;
5960     for (i=0; i<temp_size; ++i) {
5961         bit_pack (buf, *pos, 8, s[i]);
5962         *pos += 8;
5963     }
5964 }
5965 
5966 
5967 /*****************************************************************************\
5968 
5969     Function        pack_tide_record - convert TIDE_RECORD to packed form
5970 
5971     Synopsis        pack_tide_record (rec, bufptr, bufsize);
5972 
5973                     TIDE_RECORD *rec        tide record (in)
5974                     NV_U_BYTE **bufptr      packed record (out)
5975                     NV_U_INT32 *bufsize     size of buf in bytes (out)
5976 
5977                     buf is allocated by pack_tide_record and should be
5978                     freed by the caller.
5979 
5980     Returns         void
5981 
5982     Author          Extracted from write_tide_record by David Flater
5983     Date            2006-05-26
5984 
5985 \*****************************************************************************/
5986 
pack_tide_record(TIDE_RECORD * rec,NV_U_BYTE ** bufptr,NV_U_INT32 * bufsize)5987 static void pack_tide_record (TIDE_RECORD *rec, NV_U_BYTE **bufptr,
5988                               NV_U_INT32 *bufsize) {
5989     NV_U_INT32              i, pos, constituent_count;
5990     NV_INT32                temp_int;
5991     NV_U_BYTE               *buf;
5992 
5993     /* Validate input */
5994     assert (rec);
5995     /* Cursory check for buffer overflows.  Should not happen here --
5996        check_tide_record does a more thorough job when called by add_tide_record
5997        and update_tide_record. */
5998     boundscheck_oneliner (rec->header.name);
5999     boundscheck_oneliner (rec->source);
6000     boundscheck_monologue (rec->comments);
6001     boundscheck_monologue (rec->notes);
6002     boundscheck_oneliner (rec->station_id_context);
6003     boundscheck_oneliner (rec->station_id);
6004     boundscheck_monologue (rec->xfields);
6005 
6006     constituent_count = figure_size (rec);
6007 
6008     if (!(*bufptr = (NV_U_BYTE *) calloc (rec->header.record_size,
6009                                           sizeof (NV_U_BYTE)))) {
6010         perror ("libtcd can't allocate memory in pack_tide_record");
6011         exit (-1);
6012     }
6013     buf = *bufptr; /* To conserve asterisks */
6014 
6015     /*  Bit pack the common section.  "pos" is the bit position within the
6016         buffer "buf".  */
6017 
6018     pos = 0;
6019 
6020     bit_pack (buf, pos, hd.record_size_bits, rec->header.record_size);
6021     pos += hd.record_size_bits;
6022 
6023     bit_pack (buf, pos, hd.record_type_bits, rec->header.record_type);
6024     pos += hd.record_type_bits;
6025 
6026     temp_int = NINT (rec->header.latitude * hd.latitude_scale);
6027     bit_pack (buf, pos, hd.latitude_bits, temp_int);
6028     pos += hd.latitude_bits;
6029 
6030     temp_int = NINT (rec->header.longitude * hd.longitude_scale);
6031     bit_pack (buf, pos, hd.longitude_bits, temp_int);
6032     pos += hd.longitude_bits;
6033 
6034     /* This ordering doesn't match everywhere else but there's no technical
6035        reason to change it from its V1 ordering.  To do so would force
6036        another conditional in unpack_partial_tide_record. */
6037 
6038     bit_pack (buf, pos, hd.tzfile_bits, rec->header.tzfile);
6039     pos += hd.tzfile_bits;
6040 
6041     pack_string (buf, &pos, clip_string(rec->header.name));
6042 
6043     bit_pack (buf, pos, hd.station_bits, rec->header.reference_station);
6044     pos += hd.station_bits;
6045 
6046     bit_pack (buf, pos, hd.country_bits, rec->country);
6047     pos += hd.country_bits;
6048 
6049     pack_string (buf, &pos, clip_string(rec->source));
6050 
6051     bit_pack (buf, pos, hd.restriction_bits, rec->restriction);
6052     pos += hd.restriction_bits;
6053 
6054     pack_string (buf, &pos, clip_string(rec->comments));
6055     pack_string (buf, &pos, clip_string(rec->notes));
6056 
6057     bit_pack (buf, pos, hd.legalese_bits, rec->legalese);
6058     pos += hd.legalese_bits;
6059 
6060     pack_string (buf, &pos, clip_string(rec->station_id_context));
6061     pack_string (buf, &pos, clip_string(rec->station_id));
6062 
6063     bit_pack (buf, pos, hd.date_bits, rec->date_imported);
6064     pos += hd.date_bits;
6065 
6066     /* No clipping on xfields -- trailing \n required by syntax */
6067     pack_string (buf, &pos, rec->xfields);
6068 
6069     bit_pack (buf, pos, hd.dir_unit_bits, rec->direction_units);
6070     pos += hd.dir_unit_bits;
6071 
6072     bit_pack (buf, pos, hd.direction_bits, rec->min_direction);
6073     pos += hd.direction_bits;
6074 
6075     bit_pack (buf, pos, hd.direction_bits, rec->max_direction);
6076     pos += hd.direction_bits;
6077 
6078     /* The units-to-level-units compatibility hack is in check_tide_record */
6079     bit_pack (buf, pos, hd.level_unit_bits, rec->level_units);
6080     pos += hd.level_unit_bits;
6081 
6082     /*  Bit pack record type 1 records.  */
6083 
6084     if (rec->header.record_type == REFERENCE_STATION) {
6085         temp_int = NINT (rec->datum_offset * hd.datum_offset_scale);
6086         bit_pack (buf, pos, hd.datum_offset_bits, temp_int);
6087         pos += hd.datum_offset_bits;
6088 
6089         bit_pack (buf, pos, hd.datum_bits, rec->datum);
6090         pos += hd.datum_bits;
6091 
6092         bit_pack (buf, pos, hd.time_bits, rec->zone_offset);
6093         pos += hd.time_bits;
6094 
6095         bit_pack (buf, pos, hd.date_bits, rec->expiration_date);
6096         pos += hd.date_bits;
6097 
6098         bit_pack (buf, pos, hd.months_on_station_bits,
6099                   rec->months_on_station);
6100         pos += hd.months_on_station_bits;
6101 
6102         bit_pack (buf, pos, hd.date_bits, rec->last_date_on_station);
6103         pos += hd.date_bits;
6104 
6105         bit_pack (buf, pos, hd.confidence_value_bits, rec->confidence);
6106         pos += hd.confidence_value_bits;
6107 
6108         bit_pack (buf, pos, hd.constituent_bits, constituent_count);
6109         pos += hd.constituent_bits;
6110 
6111         for (i = 0 ; i < hd.pub.constituents ; ++i)
6112         {
6113             if (rec->amplitude[i] >= AMPLITUDE_EPSILON)
6114             {
6115                 bit_pack (buf, pos, hd.constituent_bits, i);
6116                 pos += hd.constituent_bits;
6117 
6118                 temp_int = NINT (rec->amplitude[i] * hd.amplitude_scale);
6119                 assert (temp_int);
6120                 bit_pack (buf, pos, hd.amplitude_bits, temp_int);
6121                 pos += hd.amplitude_bits;
6122 
6123                 temp_int = NINT (rec->epoch[i] * hd.epoch_scale);
6124                 bit_pack (buf, pos, hd.epoch_bits, temp_int);
6125                 pos += hd.epoch_bits;
6126             }
6127         }
6128     }
6129 
6130     /*  Bit pack record type 2 records.  */
6131     else if (rec->header.record_type == SUBORDINATE_STATION) {
6132         bit_pack (buf, pos, hd.time_bits, rec->min_time_add);
6133         pos += hd.time_bits;
6134 
6135         temp_int = NINT (rec->min_level_add * hd.level_add_scale);
6136         bit_pack (buf, pos, hd.level_add_bits, temp_int);
6137         pos += hd.level_add_bits;
6138 
6139         temp_int = NINT (rec->min_level_multiply * hd.level_multiply_scale);
6140         bit_pack (buf, pos, hd.level_multiply_bits, temp_int);
6141         pos += hd.level_multiply_bits;
6142 
6143         bit_pack (buf, pos, hd.time_bits, rec->max_time_add);
6144         pos += hd.time_bits;
6145 
6146         temp_int = NINT (rec->max_level_add * hd.level_add_scale);
6147         bit_pack (buf, pos, hd.level_add_bits, temp_int);
6148         pos += hd.level_add_bits;
6149 
6150         temp_int = NINT (rec->max_level_multiply * hd.level_multiply_scale);
6151         bit_pack (buf, pos, hd.level_multiply_bits, temp_int);
6152         pos += hd.level_multiply_bits;
6153 
6154         bit_pack (buf, pos, hd.time_bits, rec->flood_begins);
6155         pos += hd.time_bits;
6156 
6157         bit_pack (buf, pos, hd.time_bits, rec->ebb_begins);
6158         pos += hd.time_bits;
6159     }
6160 
6161     else {
6162         LOG_ERROR ("libtcd error:  Record type %d is undefined\n",
6163                  rec->header.record_type);
6164         exit (-1);
6165     }
6166 
6167     *bufsize = rec->header.record_size;
6168     assert (*bufsize == bits2bytes (pos));
6169 }
6170 
6171 
6172 /*****************************************************************************\
6173 
6174     Function        write_tide_record - writes a tide record to the database
6175 
6176     Synopsis        write_tide_record (num, rec);
6177 
6178                     NV_INT32 num            record number:
6179                                             >= 0 overwrite record num
6180                                               -1 write at current file position
6181                     TIDE_RECORD *rec        tide record
6182 
6183     Returns         NV_BOOL                 NVTrue if successful
6184 
6185     Author          Jan C. Depner
6186     Date            08/01/02
6187 
6188     See libtcd.html for changelog.
6189 
6190     hd.end_of_file is not updated by this function in any event.
6191 
6192 \*****************************************************************************/
6193 
write_tide_record(NV_INT32 num,TIDE_RECORD * rec)6194 static NV_BOOL write_tide_record (NV_INT32 num, TIDE_RECORD *rec)
6195 {
6196     NV_U_BYTE               *buf = NULL;
6197     NV_U_INT32              bufsize = 0;
6198 
6199     if (!fp) {
6200         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
6201         return NVFalse;
6202     }
6203     write_protect();
6204 
6205     pack_tide_record (rec, &buf, &bufsize);
6206 
6207     if (num == -1)
6208         ;
6209     else if (num >= 0)
6210         fseek (fp, tindex[num].address, SEEK_SET);
6211     else
6212         assert (0);
6213 
6214     chk_fwrite (buf, bufsize, 1, fp);
6215     free (buf);
6216     modified = NVTrue;
6217     return NVTrue;
6218 }
6219 
6220 
6221 /*****************************************************************************\
6222 
6223     Function        read_next_tide_record - reads the next tide record from
6224                     the database
6225 
6226     Synopsis        read_next_tide_record (rec);
6227 
6228                     TIDE_RECORD *rec        tide record
6229 
6230     Returns         NV_INT32                record number of the tide record
6231 
6232     Author          Jan C. Depner
6233     Date            08/01/02
6234 
6235     See libtcd.html for changelog.
6236 
6237 \*****************************************************************************/
6238 
read_next_tide_record(TIDE_RECORD * rec)6239 NV_INT32 read_next_tide_record (TIDE_RECORD *rec)
6240 {
6241     return (read_tide_record (current_record + 1, rec));
6242 }
6243 
6244 
6245 /*****************************************************************************\
6246 
6247     Function        unpack_tide_record - convert TIDE_RECORD from packed form
6248 
6249     Synopsis        unpack_tide_record (buf, bufsize, rec);
6250 
6251                     NV_U_BYTE *buf          packed record (in)
6252                     NV_U_INT32 bufsize      size of buf in bytes (in)
6253                     TIDE_RECORD *rec        tide record (in-out)
6254 
6255                     rec must be allocated by the caller.
6256 
6257     Returns         void
6258 
6259     Author          Extracted from read_tide_record by David Flater
6260     Date            2006-05-26
6261 
6262     rec->header.record_number is initialized from the global current_record.
6263 
6264 \*****************************************************************************/
6265 
unpack_tide_record(NV_U_BYTE * buf,NV_U_INT32 bufsize,TIDE_RECORD * rec)6266 static void unpack_tide_record (NV_U_BYTE *buf, NV_U_INT32 bufsize,
6267                                 TIDE_RECORD *rec) {
6268     NV_INT32                temp_int;
6269     NV_U_INT32              i, j, pos, count;
6270 
6271     assert (rec);
6272 
6273     /* Initialize record */
6274     memset (rec, 0, sizeof (TIDE_RECORD));
6275     {
6276         int r = find_dir_units ("degrees true");
6277         assert (r > 0);
6278         rec->direction_units = (NV_U_BYTE)r;
6279     }
6280     rec->min_direction = rec->max_direction = 361;
6281     rec->flood_begins = rec->ebb_begins = NULLSLACKOFFSET;
6282     rec->header.record_number = current_record;
6283 
6284     unpack_partial_tide_record (buf, bufsize, rec, &pos);
6285 
6286     switch (rec->header.record_type) {
6287     case REFERENCE_STATION:
6288     case SUBORDINATE_STATION:
6289         break;
6290     default:
6291         LOG_ERROR ("libtcd fatal error: tried to read type %d tide record.\n", rec->header.record_type);
6292         LOG_ERROR ("This version of libtcd only supports types 1 and 2.  Perhaps you should\nupgrade.\n");
6293         exit (-1);
6294     }
6295 
6296     switch (hd.pub.major_rev) {
6297 
6298         /************************* TCD V1 *****************************/
6299     case 0:
6300     case 1:
6301 
6302         /*  "pos" is the bit position within the buffer "buf".  */
6303 
6304         rec->country = bit_unpack (buf, pos, hd.country_bits);
6305         pos += hd.country_bits;
6306 
6307         /* pedigree */
6308         pos += hd.pedigree_bits;
6309 
6310         unpack_string (buf, bufsize, &pos, rec->source, ONELINER_LENGTH, "source field");
6311 
6312         rec->restriction = bit_unpack (buf, pos, hd.restriction_bits);
6313         pos += hd.restriction_bits;
6314 
6315         unpack_string (buf, bufsize, &pos, rec->comments, MONOLOGUE_LENGTH, "comments field");
6316 
6317         if (rec->header.record_type == REFERENCE_STATION) {
6318             rec->level_units = bit_unpack (buf, pos, hd.level_unit_bits);
6319 #ifdef COMPAT114
6320             rec->units = rec->level_units;
6321 #endif
6322             pos += hd.level_unit_bits;
6323 
6324             temp_int = signed_bit_unpack (buf, pos, hd.datum_offset_bits);
6325             rec->datum_offset = (NV_FLOAT32) temp_int / hd.datum_offset_scale;
6326             pos += hd.datum_offset_bits;
6327 
6328             rec->datum = bit_unpack (buf, pos, hd.datum_bits);
6329             pos += hd.datum_bits;
6330 
6331             rec->zone_offset = signed_bit_unpack (buf, pos, hd.time_bits);
6332             pos += hd.time_bits;
6333 
6334             rec->expiration_date = bit_unpack (buf, pos, hd.date_bits);
6335             pos += hd.date_bits;
6336 
6337             rec->months_on_station = bit_unpack (buf, pos,
6338                                                  hd.months_on_station_bits);
6339             pos += hd.months_on_station_bits;
6340 
6341             rec->last_date_on_station = bit_unpack (buf, pos, hd.date_bits);
6342             pos += hd.date_bits;
6343 
6344             rec->confidence = bit_unpack (buf, pos, hd.confidence_value_bits);
6345             pos += hd.confidence_value_bits;
6346 
6347             for (i = 0 ; i < hd.pub.constituents ; ++i) {
6348                 rec->amplitude[i] = 0.0;
6349                 rec->epoch[i] = 0.0;
6350             }
6351 
6352             count = bit_unpack (buf, pos, hd.constituent_bits);
6353             pos += hd.constituent_bits;
6354 
6355             for (i = 0 ; i < count ; ++i) {
6356                 j = bit_unpack (buf, pos, hd.constituent_bits);
6357                 pos += hd.constituent_bits;
6358 
6359                 rec->amplitude[j] = (NV_FLOAT32) bit_unpack (buf, pos,
6360                                     hd.amplitude_bits) / hd.amplitude_scale;
6361                 pos += hd.amplitude_bits;
6362 
6363                 rec->epoch[j] = (NV_FLOAT32) bit_unpack (buf, pos, hd.epoch_bits) /
6364                                 hd.epoch_scale;
6365                 pos += hd.epoch_bits;
6366             }
6367         } else if (rec->header.record_type == SUBORDINATE_STATION) {
6368             rec->level_units = bit_unpack (buf, pos, hd.level_unit_bits);
6369             pos += hd.level_unit_bits;
6370 
6371             rec->direction_units = bit_unpack (buf, pos, hd.dir_unit_bits);
6372             pos += hd.dir_unit_bits;
6373 
6374             /* avg_level_units */
6375             pos += hd.level_unit_bits;
6376 
6377             rec->min_time_add = signed_bit_unpack (buf, pos, hd.time_bits);
6378             pos += hd.time_bits;
6379 
6380             temp_int = signed_bit_unpack (buf, pos, hd.level_add_bits);
6381             rec->min_level_add = (NV_FLOAT32) temp_int / hd.level_add_scale;
6382             pos += hd.level_add_bits;
6383 
6384             /* Signed in V1 */
6385             temp_int = signed_bit_unpack (buf, pos, hd.level_multiply_bits);
6386             rec->min_level_multiply = (NV_FLOAT32) temp_int /
6387                                       hd.level_multiply_scale;
6388             pos += hd.level_multiply_bits;
6389 
6390             /* min_avg_level */
6391             pos += hd.level_add_bits;
6392 
6393             rec->min_direction = bit_unpack (buf, pos, hd.direction_bits);
6394             pos += hd.direction_bits;
6395 
6396             rec->max_time_add = signed_bit_unpack (buf, pos, hd.time_bits);
6397             pos += hd.time_bits;
6398 
6399             temp_int = signed_bit_unpack (buf, pos, hd.level_add_bits);
6400             rec->max_level_add = (NV_FLOAT32) temp_int / hd.level_add_scale;
6401             pos += hd.level_add_bits;
6402 
6403             /* Signed in V1 */
6404             temp_int = signed_bit_unpack (buf, pos, hd.level_multiply_bits);
6405             rec->max_level_multiply = (NV_FLOAT32) temp_int /
6406                                       hd.level_multiply_scale;
6407             pos += hd.level_multiply_bits;
6408 
6409             /* max_avg_level */
6410             pos += hd.level_add_bits;
6411 
6412             rec->max_direction = bit_unpack (buf, pos, hd.direction_bits);
6413             pos += hd.direction_bits;
6414 
6415             rec->flood_begins = signed_bit_unpack (buf, pos, hd.time_bits);
6416             pos += hd.time_bits;
6417 
6418             rec->ebb_begins = signed_bit_unpack (buf, pos, hd.time_bits);
6419             pos += hd.time_bits;
6420         } else {
6421             assert (0);
6422         }
6423         break;
6424 
6425         /************************* TCD V2 *****************************/
6426     case 2:
6427         rec->country = bit_unpack (buf, pos, hd.country_bits);
6428         pos += hd.country_bits;
6429 
6430         unpack_string (buf, bufsize, &pos, rec->source, ONELINER_LENGTH, "source field");
6431 
6432         rec->restriction = bit_unpack (buf, pos, hd.restriction_bits);
6433         pos += hd.restriction_bits;
6434 
6435         unpack_string (buf, bufsize, &pos, rec->comments, MONOLOGUE_LENGTH, "comments field");
6436         unpack_string (buf, bufsize, &pos, rec->notes, MONOLOGUE_LENGTH, "notes field");
6437 
6438         rec->legalese = bit_unpack (buf, pos, hd.legalese_bits);
6439         pos += hd.legalese_bits;
6440 
6441         unpack_string (buf, bufsize, &pos, rec->station_id_context, ONELINER_LENGTH, "station_id_context field");
6442         unpack_string (buf, bufsize, &pos, rec->station_id, ONELINER_LENGTH, "station_id field");
6443 
6444         rec->date_imported = bit_unpack (buf, pos, hd.date_bits);
6445         pos += hd.date_bits;
6446 
6447         unpack_string (buf, bufsize, &pos, rec->xfields, MONOLOGUE_LENGTH, "xfields field");
6448 
6449         rec->direction_units = bit_unpack (buf, pos, hd.dir_unit_bits);
6450         pos += hd.dir_unit_bits;
6451 
6452         rec->min_direction = bit_unpack (buf, pos, hd.direction_bits);
6453         pos += hd.direction_bits;
6454 
6455         rec->max_direction = bit_unpack (buf, pos, hd.direction_bits);
6456         pos += hd.direction_bits;
6457 
6458         rec->level_units = bit_unpack (buf, pos, hd.level_unit_bits);
6459 #ifdef COMPAT114
6460         rec->units = rec->level_units;
6461 #endif
6462         pos += hd.level_unit_bits;
6463 
6464         if (rec->header.record_type == REFERENCE_STATION) {
6465             temp_int = signed_bit_unpack (buf, pos, hd.datum_offset_bits);
6466             rec->datum_offset = (NV_FLOAT32) temp_int / hd.datum_offset_scale;
6467             pos += hd.datum_offset_bits;
6468 
6469             rec->datum = bit_unpack (buf, pos, hd.datum_bits);
6470             pos += hd.datum_bits;
6471 
6472             rec->zone_offset = signed_bit_unpack (buf, pos, hd.time_bits);
6473             pos += hd.time_bits;
6474 
6475             rec->expiration_date = bit_unpack (buf, pos, hd.date_bits);
6476             pos += hd.date_bits;
6477 
6478             rec->months_on_station = bit_unpack (buf, pos,
6479                                                  hd.months_on_station_bits);
6480             pos += hd.months_on_station_bits;
6481 
6482             rec->last_date_on_station = bit_unpack (buf, pos, hd.date_bits);
6483             pos += hd.date_bits;
6484 
6485             rec->confidence = bit_unpack (buf, pos, hd.confidence_value_bits);
6486             pos += hd.confidence_value_bits;
6487 
6488             for (i = 0 ; i < hd.pub.constituents ; ++i) {
6489                 rec->amplitude[i] = 0.0;
6490                 rec->epoch[i] = 0.0;
6491             }
6492 
6493             count = bit_unpack (buf, pos, hd.constituent_bits);
6494             pos += hd.constituent_bits;
6495 
6496             for (i = 0 ; i < count ; ++i) {
6497                 j = bit_unpack (buf, pos, hd.constituent_bits);
6498                 pos += hd.constituent_bits;
6499 
6500                 rec->amplitude[j] = (NV_FLOAT32) bit_unpack (buf, pos,
6501                                     hd.amplitude_bits) / hd.amplitude_scale;
6502                 pos += hd.amplitude_bits;
6503 
6504                 rec->epoch[j] = (NV_FLOAT32) bit_unpack (buf, pos, hd.epoch_bits) /
6505                                 hd.epoch_scale;
6506                 pos += hd.epoch_bits;
6507             }
6508         } else if (rec->header.record_type == SUBORDINATE_STATION) {
6509             rec->min_time_add = signed_bit_unpack (buf, pos, hd.time_bits);
6510             pos += hd.time_bits;
6511 
6512             temp_int = signed_bit_unpack (buf, pos, hd.level_add_bits);
6513             rec->min_level_add = (NV_FLOAT32) temp_int / hd.level_add_scale;
6514             pos += hd.level_add_bits;
6515 
6516             /* Made unsigned in V2 */
6517             temp_int = bit_unpack (buf, pos, hd.level_multiply_bits);
6518             rec->min_level_multiply = (NV_FLOAT32) temp_int /
6519                                       hd.level_multiply_scale;
6520             pos += hd.level_multiply_bits;
6521 
6522             rec->max_time_add = signed_bit_unpack (buf, pos, hd.time_bits);
6523             pos += hd.time_bits;
6524 
6525             temp_int = signed_bit_unpack (buf, pos, hd.level_add_bits);
6526             rec->max_level_add = (NV_FLOAT32) temp_int / hd.level_add_scale;
6527             pos += hd.level_add_bits;
6528 
6529             /* Made unsigned in V2 */
6530             temp_int = bit_unpack (buf, pos, hd.level_multiply_bits);
6531             rec->max_level_multiply = (NV_FLOAT32) temp_int /
6532                                       hd.level_multiply_scale;
6533             pos += hd.level_multiply_bits;
6534 
6535             rec->flood_begins = signed_bit_unpack (buf, pos, hd.time_bits);
6536             pos += hd.time_bits;
6537 
6538             rec->ebb_begins = signed_bit_unpack (buf, pos, hd.time_bits);
6539             pos += hd.time_bits;
6540         } else {
6541             assert (0);
6542         }
6543         break;
6544 
6545     default:
6546         assert (0);
6547     }
6548 
6549     assert (pos <= bufsize*8);
6550 }
6551 
6552 
6553 /*****************************************************************************\
6554 
6555     Function        read_tide_record - reads tide record "num" from the
6556                     database
6557 
6558     Synopsis        read_tide_record (num, rec);
6559 
6560                     NV_INT32 num            record number (in)
6561                     TIDE_RECORD *rec        tide record (in-out)
6562 
6563                     rec must be allocated by the caller.
6564 
6565     Returns         NV_INT32                num if success, -1 if failure
6566 
6567     Author          Jan C. Depner
6568     Date            08/01/02
6569 
6570     See libtcd.html for changelog.
6571 
6572 \*****************************************************************************/
6573 
read_tide_record(NV_INT32 num,TIDE_RECORD * rec)6574 NV_INT32 read_tide_record (NV_INT32 num, TIDE_RECORD *rec)
6575 {
6576     NV_U_BYTE               *buf;
6577     NV_U_INT32              bufsize;
6578 
6579     if (!fp) {
6580         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
6581         return -1;
6582     }
6583 
6584     if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
6585         return -1;
6586     assert (rec);
6587 
6588     bufsize = tindex[num].record_size;
6589     if ((buf = (NV_U_BYTE *) calloc (bufsize, sizeof (NV_U_BYTE))) == NULL)
6590     {
6591         perror ("Allocating read_tide_record buffer");
6592         exit (-1);
6593     }
6594 
6595     current_record = num;
6596     require (fseek (fp, tindex[num].address, SEEK_SET) == 0);
6597     chk_fread (buf, tindex[num].record_size, 1, fp);
6598     unpack_tide_record (buf, bufsize, rec);
6599     free (buf);
6600     return num;
6601 }
6602 
6603 
6604 /*****************************************************************************\
6605 
6606     Function        add_tide_record - adds a tide record to the database
6607 
6608     Synopsis        add_tide_record (rec);
6609 
6610                     TIDE_RECORD *rec        tide record
6611 
6612     Returns         NV_BOOL                 NVTrue if successful
6613 
6614     Author          Jan C. Depner
6615     Date            08/01/02
6616 
6617     See libtcd.html for changelog.
6618 
6619 \*****************************************************************************/
6620 
add_tide_record(TIDE_RECORD * rec,DB_HEADER_PUBLIC * db)6621 NV_BOOL add_tide_record (TIDE_RECORD *rec, DB_HEADER_PUBLIC *db)
6622 {
6623     NV_INT32                pos;
6624 
6625     if (!fp) {
6626         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
6627         return NVFalse;
6628     }
6629     write_protect();
6630 
6631     if (!check_tide_record (rec))
6632         return NVFalse;
6633 
6634     fseek (fp, hd.end_of_file, SEEK_SET);
6635     pos = ftell (fp);
6636     assert (pos > 0);
6637 
6638     rec->header.record_number = hd.pub.number_of_records++;
6639 
6640     if (write_tide_record (-1, rec))
6641     {
6642         if ((tindex = (TIDE_INDEX *) realloc (tindex, hd.pub.number_of_records *
6643                                               sizeof (TIDE_INDEX))) == NULL)
6644         {
6645             perror ("Allocating more index records");
6646             exit (-1);
6647         }
6648 
6649         tindex[rec->header.record_number].address = pos;
6650         tindex[rec->header.record_number].record_size = rec->header.record_size;
6651         tindex[rec->header.record_number].record_type = rec->header.record_type;
6652         tindex[rec->header.record_number].reference_station =
6653             rec->header.reference_station;
6654         assert (rec->header.tzfile >= 0);
6655         tindex[rec->header.record_number].tzfile = rec->header.tzfile;
6656         tindex[rec->header.record_number].lat = NINT (rec->header.latitude *
6657                                                 hd.latitude_scale);
6658         tindex[rec->header.record_number].lon = NINT (rec->header.longitude *
6659                                                 hd.longitude_scale);
6660 
6661 
6662         if ((tindex[rec->header.record_number].name =
6663                     (NV_CHAR *) calloc (strlen (rec->header.name) + 1,
6664                                         sizeof (NV_CHAR))) == NULL)
6665         {
6666             perror ("Allocating index name memory");
6667             exit (-1);
6668         }
6669 
6670 
6671         strcpy (tindex[rec->header.record_number].name, rec->header.name);
6672         pos = ftell (fp);
6673         assert (pos > 0);
6674         hd.end_of_file = pos;
6675         modified = NVTrue;
6676 
6677         /*  Get the new number of records.  */
6678         if (db)
6679             *db = hd.pub;
6680 
6681         return NVTrue;
6682     }
6683 
6684     return NVFalse;
6685 }
6686 
6687 #if 0
6688 /*****************************************************************************\
6689 
6690     Function        delete_tide_record - deletes a record and all subordinate
6691                     records from the database
6692 
6693     Synopsis        delete_tide_record (num);
6694 
6695                     NV_INT32 num            record number
6696 
6697     Returns         NV_BOOL                 NVTrue if successful
6698 
6699     Author          Jan C. Depner (redone by David Flater)
6700     Date            08/01/02 (2006-05-26)
6701 
6702     See libtcd.html for changelog.
6703 
6704 \*****************************************************************************/
6705 
6706 NV_BOOL delete_tide_record (NV_INT32 num, DB_HEADER_PUBLIC *db)
6707 {
6708     NV_INT32          i, newrecnum, *map;
6709     NV_U_BYTE         **allrecs_packed;
6710 
6711     if (!fp) {
6712         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
6713         return NVFalse;
6714     }
6715     write_protect();
6716 
6717     if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records) return NVFalse;
6718 
6719     /* Allocate workspace */
6720 
6721     if (!(map = (NV_INT32 *) malloc (hd.pub.number_of_records * sizeof(NV_INT32)))) {
6722         perror ("libtcd: delete_tide_record: can't malloc");
6723         return NVFalse;
6724     }
6725     if (!(allrecs_packed = (NV_U_BYTE **) malloc (hd.pub.number_of_records * sizeof(NV_U_BYTE*)))) {
6726         perror ("libtcd: delete_tide_record: can't malloc");
6727         free (map);
6728         return NVFalse;
6729     }
6730 
6731     /* First pass: read in database, build record number map and mark records
6732        for deletion */
6733 
6734     require (fseek (fp, tindex[0].address, SEEK_SET) == 0);
6735     for (newrecnum=0,i=0; i<(NV_INT32)hd.pub.number_of_records; ++i) {
6736         assert (ftell(fp) == tindex[i].address);
6737         if (i == num || (tindex[i].record_type == SUBORDINATE_STATION && tindex[i].reference_station == num)) {
6738             map[i] = -1;
6739             allrecs_packed[i] = NULL;
6740             require (fseek (fp, tindex[i].record_size, SEEK_CUR) == 0);
6741         } else {
6742             map[i] = newrecnum++;
6743             if (!(allrecs_packed[i] = (NV_U_BYTE *) malloc (tindex[i].record_size))) {
6744                 perror ("libtcd: delete_tide_record: can't malloc");
6745                 for (--i; i>=0; --i)
6746                     free (allrecs_packed[i]);
6747                 free (allrecs_packed);
6748                 free (map);
6749                 return NVFalse;
6750             }
6751             chk_fread (allrecs_packed[i], tindex[i].record_size, 1, fp);
6752         }
6753     }
6754 
6755     /* Second pass: rewrite database and fix substation linkage */
6756 
6757     require (fseek (fp, tindex[0].address, SEEK_SET) == 0);
6758     require (ftruncate (fileno(fp), tindex[0].address) == 0);
6759 
6760     for (i=0; i<(NV_INT32)hd.pub.number_of_records; ++i)
6761         if (map[i] >= 0) {
6762             if (tindex[i].record_type == SUBORDINATE_STATION) {
6763                 assert (tindex[i].reference_station >= 0);
6764                 assert (tindex[i].reference_station <= (NV_INT32)hd.pub.number_of_records);
6765                 if (map[tindex[i].reference_station] != tindex[i].reference_station) {
6766                     /* Fix broken reference station linkage */
6767                     TIDE_RECORD rec;
6768                     unpack_tide_record (allrecs_packed[i], tindex[i].record_size, &rec);
6769                     free (allrecs_packed[i]);
6770                     rec.header.reference_station = map[tindex[i].reference_station];
6771                     pack_tide_record (&rec, &(allrecs_packed[i]), &(tindex[i].record_size));
6772                 }
6773             }
6774             chk_fwrite (allrecs_packed[i], tindex[i].record_size, 1, fp);
6775             free (allrecs_packed[i]);
6776         }
6777 
6778     /* Free workspace (packed records were freed above) */
6779 
6780     free (allrecs_packed);
6781     free (map);
6782 
6783     /* Flush, reopen, renew.  The index is now garbage; close and reopen
6784        to reindex. */
6785 
6786     hd.end_of_file = ftell(fp);
6787     hd.pub.number_of_records = newrecnum;
6788     modified = NVTrue;
6789     close_tide_db ();
6790     open_tide_db (filename);
6791 
6792     if (db)
6793         *db = hd.pub;
6794 
6795     return NVTrue;
6796 }
6797 
6798 #endif
6799 
6800 /*****************************************************************************\
6801 
6802     Function        update_tide_record - updates a tide record in the database
6803 
6804     Synopsis        update_tide_record (num, rec);
6805 
6806                     NV_INT32 num            record number
6807                     TIDE_RECORD *rec        tide record
6808 
6809     Returns         NV_BOOL                 NVTrue if successful
6810 
6811     Author          Jan C. Depner
6812     Date            08/01/02
6813 
6814     See libtcd.html for changelog.
6815 
6816 \*****************************************************************************/
6817 
6818 #ifdef COMPAT114
update_tide_record(NV_INT32 num,TIDE_RECORD * rec)6819 NV_BOOL update_tide_record (NV_INT32 num, TIDE_RECORD *rec)
6820 #else
6821 NV_BOOL update_tide_record (NV_INT32 num, TIDE_RECORD *rec, DB_HEADER_PUBLIC *db)
6822 #endif
6823 {
6824     NV_INT32                pos, size;
6825     TIDE_RECORD             tmp_rec;
6826     NV_U_BYTE               *block = NULL;
6827 
6828     if (!fp) {
6829         LOG_ERROR ("libtcd error: attempt to access database when database not open\n");
6830         return NVFalse;
6831     }
6832     write_protect();
6833 
6834     if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records) return NVFalse;
6835 
6836     if (!check_tide_record (rec))
6837         return NVFalse;
6838 
6839     figure_size (rec);
6840     read_tide_record (num, &tmp_rec);
6841     if (rec->header.record_size != tmp_rec.header.record_size)
6842     {
6843         /*  Aaaaaaarrrrrgggggghhhh!!!!  We have to move stuff!  */
6844 
6845         /*  Save where we are - end of record being modified.  */
6846         pos = ftell (fp);
6847         assert (pos > 0);
6848 
6849         /*  Figure out how big a block we need to move.  */
6850         size = hd.end_of_file - pos;
6851         assert (size >= 0);
6852 
6853         /*  Allocate memory and read the block.  */
6854         if (size)
6855         {
6856             if ((block = (NV_U_BYTE *) calloc (size, sizeof (NV_U_BYTE))) ==
6857                     NULL)
6858             {
6859                 perror ("Allocating block");
6860                 return NVFalse;
6861             }
6862             chk_fread (block, size, 1, fp);
6863         }
6864 
6865         /*  Write out the modified record.  */
6866         write_tide_record (num, rec);
6867 
6868         /*  If we weren't at the end of file, move the block.  */
6869         if (size)
6870         {
6871             chk_fwrite (block, size, 1, fp);
6872             free (block);
6873         }
6874 
6875         hd.end_of_file = ftell (fp);
6876 
6877         /*  Close the file and reopen it to index the records again.  */
6878         close_tide_db ();
6879         open_tide_db (filename);
6880     }
6881 
6882     /*  The easy way.  No change to the record size.  */
6883     else
6884     {
6885         write_tide_record (num, rec);
6886 
6887         /*  Save the header info in the index.  */
6888         tindex[num].record_size = rec->header.record_size;
6889         tindex[num].record_type = rec->header.record_type;
6890         tindex[num].reference_station = rec->header.reference_station;
6891         tindex[num].tzfile = rec->header.tzfile;
6892         tindex[num].lat = NINT (rec->header.latitude * hd.latitude_scale);
6893         tindex[num].lon = NINT (rec->header.longitude * hd.longitude_scale);
6894 
6895         /* AH maybe? */
6896         /* DWF: agree, same size record does not imply that name length
6897            is identical. */
6898         if (strcmp(tindex[num].name, rec->header.name) != 0) {
6899             free(tindex[num].name);
6900             tindex[num].name = (NV_CHAR *) calloc (strlen (rec->header.name) + 1, sizeof (NV_CHAR));
6901             strcpy(tindex[num].name, rec->header.name);
6902         }
6903     }
6904 
6905 #ifndef COMPAT114
6906     if (db)
6907         *db = hd.pub;
6908 #endif
6909 
6910     return (NVTrue);
6911 }
6912 
6913 
6914 /*****************************************************************************\
6915 
6916     Function        infer_constituents - computes inferred constituents when
6917                     M2, S2, K1, and O1 are given.  This function fills the
6918                     remaining unfilled constituents.  The inferred constituents
6919                     are developed or decided based on article 230 of
6920                     "Manual of Harmonic Analysis and Prediction of Tides",
6921                     Paul Schureman, C & GS special publication no. 98,
6922                     October 1971.  This function is really just for NAVO
6923                     since we go to weird places and put in tide gages for
6924                     ridiculously short periods of time so we only get a
6925                     few major constituents developed.  This function was
6926                     modified from the NAVO FORTRAN program pred_tide_corr,
6927                     subroutine infer.ftn, 08-oct-86.
6928 
6929     Synopsis        infer_constituents (rec);
6930 
6931                     TIDE_RECORD rec         tide record
6932 
6933     Returns         NV_BOOL                 NVFalse if not enough constituents
6934                                             available to infer others
6935 
6936     Author          Jan C. Depner
6937     Date            08/01/02
6938 
6939     See libtcd.html for changelog.
6940 
6941 \*****************************************************************************/
6942 
infer_constituents(TIDE_RECORD * rec)6943 NV_BOOL infer_constituents (TIDE_RECORD *rec)
6944 {
6945     NV_U_INT32        i, j;
6946     NV_INT32          m2, s2, k1, o1;
6947     NV_FLOAT32        epoch_m2, epoch_s2, epoch_k1, epoch_o1;
6948 
6949     assert (rec);
6950     require ((m2 = find_constituent ("M2")) >= 0);
6951     require ((s2 = find_constituent ("S2")) >= 0);
6952     require ((k1 = find_constituent ("K1")) >= 0);
6953     require ((o1 = find_constituent ("O1")) >= 0);
6954 
6955     if (rec->amplitude[m2] == 0.0 || rec->amplitude[s2] == 0.0 ||
6956             rec->amplitude[k1] == 0.0 || rec->amplitude[o1] == 0.0)
6957         return (NVFalse);
6958 
6959     epoch_m2 = rec->epoch[m2];
6960     epoch_s2 = rec->epoch[s2];
6961     epoch_k1 = rec->epoch[k1];
6962     epoch_o1 = rec->epoch[o1];
6963 
6964     for (i = 0 ; i < hd.pub.constituents ; ++i)
6965     {
6966         if (rec->amplitude[i] == 0.0 && rec->epoch[i] == 0.0)
6967         {
6968             for (j = 0 ; j < INFERRED_SEMI_DIURNAL_COUNT ; ++j)
6969             {
6970                 if (!strcmp (inferred_semi_diurnal[j], get_constituent (i)))
6971                 {
6972                     /*  Compute the inferred semi-diurnal constituent.  */
6973 
6974                     rec->amplitude[i] = (semi_diurnal_coeff[j] / coeff[0]) *
6975                                         rec->amplitude[m2];
6976 
6977                     if (fabs ((NV_FLOAT64) (epoch_s2 - epoch_m2)) > 180.0)
6978                     {
6979                         if (epoch_s2 < epoch_m2)
6980                         {
6981                             epoch_s2 += 360.0;
6982                         }
6983                         else
6984                         {
6985                             epoch_m2 += 360.0;
6986                         }
6987                     }
6988                     rec->epoch[i] = epoch_m2 + ((hd.speed[i] - hd.speed[m2]) /
6989                                                 (hd.speed[s2] - hd.speed[m2])) * (epoch_s2 - epoch_m2);
6990                 }
6991             }
6992 
6993 
6994             for (j = 0 ; j < INFERRED_DIURNAL_COUNT ; ++j)
6995             {
6996                 if (!strcmp (inferred_diurnal[j], get_constituent (i)))
6997                 {
6998                     /*  Compute the inferred diurnal constituent.  */
6999 
7000                     rec->amplitude[i] = (diurnal_coeff[j] / coeff[1]) *
7001                                         rec->amplitude[o1];
7002 
7003                     if (fabs ((NV_FLOAT64) (epoch_k1 - epoch_o1)) > 180.0)
7004                     {
7005                         if (epoch_k1 < epoch_o1)
7006                         {
7007                             epoch_k1 += 360.0;
7008                         }
7009                         else
7010                         {
7011                             epoch_o1 += 360.0;
7012                         }
7013                     }
7014                     rec->epoch[i] = epoch_o1 + ((hd.speed[i] - hd.speed[o1]) /
7015                                                 (hd.speed[k1] - hd.speed[o1])) * (epoch_k1 - epoch_o1);
7016                 }
7017             }
7018         }
7019     }
7020 
7021     return (NVTrue);
7022 }
7023 
7024 /* $Id: bit_pack.c 1805 2007-01-22 15:36:20Z flaterco $ */
7025 
7026 #include <math.h>
7027 #include <stdio.h>
7028 #include <assert.h>
7029 
7030 
7031 
7032 static NV_U_BYTE        mask[8] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc,
7033                                    0xfe
7034                                   }, notmask[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f,
7035                                           0x07, 0x03, 0x01
7036                                                   };
7037 
7038 
7039 /*****************************************************************************\
7040 
7041                             DISTRIBUTION STATEMENT
7042 
7043     This source file is unclassified, distribution unlimited, public
7044     domain.  It is distributed in the hope that it will be useful, but
7045     WITHOUT ANY WARRANTY; without even the implied warranty of
7046     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7047 
7048 \*****************************************************************************/
7049 
7050 
7051 
7052 /***************************************************************************\
7053 *                                                                           *
7054 *   Function        calculate_bits - Computes the number of bits needed     *
7055 *                   to store a specified value.                             *
7056 *                                                                           *
7057 *   Synopsis        calculate_bits (value);                                 *
7058 *                                                                           *
7059 *                   NV_U_INT32 value        the value to store              *
7060 *                                                                           *
7061 *   Returns         NV_U_INT32              number of bits needed           *
7062 *                                                                           *
7063 *   If value = 0, return is 0.                                              *
7064 *   No bits are needed to store a field whose only possible value is 0.     *
7065 *                                                                           *
7066 *   Author          Jan C. Depner                                           *
7067 *                                                                           *
7068 *   Rewritten by DWF 2007-01-21                                             *
7069 *     - "Range" was ambiguous and off-by-one errors existed in tide_db.c    *
7070 *     - Use of log10(x)/log10(2) was vulnerable to roundoff error           *
7071 *     - Conversion to floating point was unnecessary                        *
7072 *     - Was giving the answer 0 for the input value 1                       *
7073 *     - God only knows what it did for the input value 0 (the logarithm     *
7074 *       is undefined)                                                       *
7075 *                                                                           *
7076 \***************************************************************************/
7077 
calculate_bits(NV_U_INT32 value)7078 NV_U_INT32 calculate_bits (NV_U_INT32 value) {
7079     NV_U_INT32 bits = 32;
7080     NV_U_INT32 theBit = 0x80000000;
7081 
7082     while (value < theBit) {
7083         theBit >>= 1;
7084         --bits;
7085     }
7086     assert (bits <= 32);
7087     return bits;
7088 }
7089 
7090 
7091 
7092 /***************************************************************************\
7093 *                                                                           *
7094 *   Function        bit_pack - Packs a long value into consecutive bits in  *
7095 *                   buffer.                                                 *
7096 *                                                                           *
7097 *   Synopsis        bit_pack (buffer, start, numbits, value);               *
7098 *                                                                           *
7099 *                   NV_U_BYTE buffer[]      address of buffer to use        *
7100 *                   NV_U_INT32 start        start bit position in buffer    *
7101 *                   NV_U_INT32 numbits      number of bits to store         *
7102 *                   NV_INT32 value          value to store                  *
7103 *                                                                           *
7104 *   Description     Packs the value 'value' into 'numbits' bits in 'buffer' *
7105 *                   starting at bit position 'start'.  The majority of      *
7106 *                   this code is based on Appendix C of Naval Ocean         *
7107 *                   Research and Development Activity Report #236, 'Data    *
7108 *                   Base Structure to Support the Production of the Digital *
7109 *                   Bathymetric Data Base', Nov. 1989, James E. Braud,      *
7110 *                   John L. Breckenridge, James E. Current, Jerry L.        *
7111 *                   Landrum.                                                *
7112 *                                                                           *
7113 *   Returns         void                                                    *
7114 *                                                                           *
7115 *   Author          Jan C. Depner                                           *
7116 *                                                                           *
7117 \***************************************************************************/
7118 
bit_pack(NV_U_BYTE buffer[],NV_U_INT32 start,NV_U_INT32 numbits,NV_INT32 value)7119 void bit_pack (NV_U_BYTE buffer[], NV_U_INT32 start, NV_U_INT32 numbits,
7120                NV_INT32 value)
7121 {
7122     NV_INT32                start_byte, end_byte, start_bit, end_bit, i;
7123 
7124 
7125     i = start + numbits;
7126 
7127 
7128     /*  Right shift the start and end by 3 bits, this is the same as        */
7129     /*  dividing by 8 but is faster.  This is computing the start and end   */
7130     /*  bytes for the field.                                                */
7131 
7132     start_byte = start >> 3;
7133     end_byte = i >> 3;
7134 
7135 
7136     /*  AND the start and end bit positions with 7, this is the same as     */
7137     /*  doing a mod with 8 but is faster.  Here we are computing the start  */
7138     /*  and end bits within the start and end bytes for the field.          */
7139 
7140     start_bit = start & 7;
7141     end_bit = i & 7;
7142 
7143 
7144     /*  Compute the number of bytes covered.                                */
7145 
7146     i = end_byte - start_byte - 1;
7147 
7148 
7149     /*  If the value is to be stored in one byte, store it.                 */
7150 
7151     if (start_byte == end_byte)
7152     {
7153         /*  Rather tricky.  We are masking out anything prior to the start  */
7154         /*  bit and after the end bit in order to not corrupt data that has */
7155         /*  already been stored there.                                      */
7156 
7157         buffer[start_byte] &= mask[start_bit] | notmask[end_bit];
7158 
7159 
7160         /*  Now we mask out anything in the value that is prior to the      */
7161         /*  start bit and after the end bit.  This is, of course, after we  */
7162         /*  have shifted the value left past the end bit.                   */
7163 
7164         buffer[start_byte] |= (value << (8 - end_bit)) &
7165                               (notmask[start_bit] & mask[end_bit]);
7166     }
7167 
7168 
7169     /*  If the value covers more than 1 byte, store it.                     */
7170 
7171     else
7172     {
7173         /*  Here we mask out data prior to the start bit of the first byte. */
7174 
7175         buffer[start_byte] &= mask[start_bit];
7176 
7177 
7178         /*  Get the upper bits of the value and mask out anything prior to  */
7179         /*  the start bit.  As an example of what's happening here, if we   */
7180         /*  wanted to store a 14 bit field and the start bit for the first  */
7181         /*  byte is 3, we would be storing the upper 5 bits of the value in */
7182         /*  the first byte.                                                 */
7183 
7184         buffer[start_byte++] |= (value >> (numbits - (8 - start_bit))) &
7185                                 notmask[start_bit];
7186 
7187 
7188         /*  Loop while decrementing the byte counter.                       */
7189 
7190         while (i--)
7191         {
7192             /*  Clear the entire byte.                                      */
7193 
7194             buffer[start_byte] &= 0;
7195 
7196 
7197             /*  Get the next 8 bits from the value.                         */
7198 
7199             buffer[start_byte++] |= (value >> ((i << 3) + end_bit)) & 255;
7200         }
7201 
7202 
7203         /*  For the last byte we mask out anything after the end bit.       */
7204 
7205         buffer[start_byte] &= notmask[end_bit];
7206 
7207 
7208         /*  Get the last part of the value and stuff it in the end byte.    */
7209         /*  The left shift effectively erases anything above 8 - end_bit    */
7210         /*  bits in the value so that it will fit in the last byte.         */
7211 
7212         buffer[start_byte] |= (value << (8 - end_bit));
7213     }
7214 }
7215 
7216 
7217 
7218 /***************************************************************************\
7219 *                                                                           *
7220 *   Function        bit_unpack - Unpacks a long value from consecutive bits *
7221 *                   in buffer.                                              *
7222 *                                                                           *
7223 *   Synopsis        bit_unpack (buffer, start, numbits);                    *
7224 *                                                                           *
7225 *                   NV_U_BYTE buffer[]      address of buffer to use        *
7226 *                   NV_U_INT32 start        start bit position in buffer    *
7227 *                   NV_U_INT32 numbits      number of bits to retrieve      *
7228 *                                                                           *
7229 *   Description     Unpacks the value from 'numbits' bits in 'buffer'       *
7230 *                   starting at bit position 'start'.  The value is assumed *
7231 *                   to be unsigned.  The majority of this code is based on  *
7232 *                   Appendix C of Naval Ocean Research and Development      *
7233 *                   Activity Report #236, 'Data Base Structure to Support   *
7234 *                   the Production of the Digital Bathymetric Data Base',   *
7235 *                   Nov. 1989, James E. Braud, John L. Breckenridge, James  *
7236 *                   E. Current, Jerry L. Landrum.                           *
7237 *                                                                           *
7238 *   Returns         NV_U_INT32              value retrieved from buffer     *
7239 *                                                                           *
7240 *   Author          Jan C. Depner                                           *
7241 *                                                                           *
7242 \***************************************************************************/
7243 
bit_unpack(NV_U_BYTE buffer[],NV_U_INT32 start,NV_U_INT32 numbits)7244 NV_U_INT32 bit_unpack (NV_U_BYTE buffer[], NV_U_INT32 start, NV_U_INT32 numbits)
7245 {
7246     NV_INT32                start_byte, end_byte, start_bit, end_bit, i;
7247     NV_U_INT32              value;
7248 
7249 
7250     i = start + numbits;
7251 
7252 
7253     /*  Right shift the start and end by 3 bits, this is the same as        */
7254     /*  dividing by 8 but is faster.  This is computing the start and end   */
7255     /*  bytes for the field.                                                */
7256 
7257     start_byte = start >> 3;
7258     end_byte = i >> 3;
7259 
7260 
7261     /*  AND the start and end bit positions with 7, this is the same as     */
7262     /*  doing a mod with 8 but is faster.  Here we are computing the start  */
7263     /*  and end bits within the start and end bytes for the field.          */
7264 
7265     start_bit = start & 7;
7266     end_bit = i & 7;
7267 
7268 
7269     /*  Compute the number of bytes covered.                                */
7270 
7271     i = end_byte - start_byte - 1;
7272 
7273 
7274     /*  If the value is stored in one byte, retrieve it.                    */
7275 
7276     if (start_byte == end_byte)
7277     {
7278         /*  Mask out anything prior to the start bit and after the end bit. */
7279 
7280         value = (NV_U_INT32) buffer[start_byte] & (notmask[start_bit] &
7281                 mask[end_bit]);
7282 
7283 
7284         /*  Now we shift the value to the right.                            */
7285 
7286         value >>= (8 - end_bit);
7287     }
7288 
7289 
7290     /*  If the value covers more than 1 byte, retrieve it.                  */
7291 
7292     else
7293     {
7294         /*  Here we mask out data prior to the start bit of the first byte  */
7295         /*  and shift to the left the necessary amount.                     */
7296 
7297         value = (NV_U_INT32) (buffer[start_byte++] & notmask[start_bit]) <<
7298                 (numbits - (8 - start_bit));
7299 
7300 
7301         /*  Loop while decrementing the byte counter.                       */
7302 
7303         while (i--)
7304         {
7305             /*  Get the next 8 bits from the buffer.                        */
7306 
7307             value += (NV_U_INT32) buffer[start_byte++] << ((i << 3) + end_bit);
7308         }
7309 
7310 
7311         /*  For the last byte we mask out anything after the end bit and    */
7312         /*  then shift to the right (8 - end_bit) bits.                     */
7313 
7314         value += (NV_U_INT32) (buffer[start_byte] & mask[end_bit]) >>
7315                  (8 - end_bit);
7316     }
7317 
7318     return (value);
7319 }
7320 
7321 
7322 
7323 /***************************************************************************\
7324 *                                                                           *
7325 *   Function        signed_bit_unpack - Unpacks a signed long value from    *
7326 *                   consecutive bits in buffer.                             *
7327 *                                                                           *
7328 *   Synopsis        signed_bit_unpack (buffer, start, numbits);             *
7329 *                                                                           *
7330 *                   NV_U_BYTE buffer[]      address of buffer to use        *
7331 *                   NV_U_INT32 start        start bit position in buffer    *
7332 *                   NV_U_INT32 numbits      number of bits to retrieve      *
7333 *                                                                           *
7334 *   Description     Unpacks the value from 'numbits' bits in 'buffer'       *
7335 *                   starting at bit position 'start'.  The value is assumed *
7336 *                   to be signed.  The majority of this code is based on    *
7337 *                   Appendix C of Naval Ocean Research and Development      *
7338 *                   Activity Report #236, 'Data Base Structure to Support   *
7339 *                   the Production of the Digital Bathymetric Data Base',   *
7340 *                   Nov. 1989, James E. Braud, John L. Breckenridge, James  *
7341 *                   E. Current, Jerry L. Landrum.                           *
7342 *                                                                           *
7343 *   Returns         NV_INT32              value retrieved from buffer       *
7344 *                                                                           *
7345 *   Author          Jan C. Depner                                           *
7346 *                                                                           *
7347 \***************************************************************************/
7348 
signed_bit_unpack(NV_U_BYTE buffer[],NV_U_INT32 start,NV_U_INT32 numbits)7349 NV_INT32 signed_bit_unpack (NV_U_BYTE buffer[], NV_U_INT32 start,
7350                             NV_U_INT32 numbits)
7351 {
7352     static NV_INT32              extend_mask = 0x7fffffff;
7353     NV_INT32                     value;
7354 
7355     /* This function is not used anywhere that this case could arise. */
7356     assert (numbits > 0);
7357 
7358     value = bit_unpack (buffer, start, numbits);
7359 
7360     if (value & (1 << (numbits - 1))) value |= (extend_mask << numbits);
7361 
7362     return (value);
7363 }
7364 
7365 
7366