1 /*
2 
3 -Procedure lstlec_c ( Last character element less than or equal to. )
4 
5 -Abstract
6 
7    Given a character string and an ordered array of character
8    strings, find the index of the largest array element less than
9    or equal to the given string.
10 
11 -Disclaimer
12 
13    THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE
14    CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S.
15    GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE
16    ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE
17    PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS"
18    TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY
19    WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A
20    PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC
21    SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE
22    SOFTWARE AND RELATED MATERIALS, HOWEVER USED.
23 
24    IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA
25    BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT
26    LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND,
27    INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS,
28    REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE
29    REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY.
30 
31    RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF
32    THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY
33    CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE
34    ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE.
35 
36 -Required_Reading
37 
38    None.
39 
40 -Keywords
41 
42    SEARCH,  ARRAY
43 
44 */
45 
46    #include "SpiceUsr.h"
47    #include "SpiceZfc.h"
48    #include "SpiceZst.h"
49    #include "SpiceZmc.h"
50    #include "f2cMang.h"
51    #undef    lstlec_c
52 
lstlec_c(ConstSpiceChar * string,SpiceInt n,SpiceInt lenvals,const void * array)53    SpiceInt lstlec_c ( ConstSpiceChar  * string,
54                        SpiceInt          n,
55                        SpiceInt          lenvals,
56                        const void      * array   )
57 /*
58 
59 -Brief_I/O
60 
61    VARIABLE  I/O  DESCRIPTION
62    --------  ---  --------------------------------------------------
63    string     I   Upper bound value to search against.
64    n          I   Number elements in array.
65    lenvals    I   String length.
66    array      I   Array of possible lower bounds.
67 
68    The function returns the index of the last element of array that
69    is lexically less than or equal to string.
70 
71 -Detailed_Input
72 
73    string      is a string acting as an upper bound:  the array element
74                that is lexically the greatest element less than or
75                equal to string is to be found.  Trailing blanks in this
76                bound value are not significant.
77 
78    n           is the dimension of the array.
79 
80    lenvals     is the declared length of the strings in the input
81                string array, including null terminators.  The input
82                array should be declared with dimension
83 
84                   [n][lenvals]
85 
86    array       is the array of character strings to be searched.
87                Trailing blanks in the strings in this array are not
88                significant. The strings must be sorted in
89                non-decreasing order. The elements of array need not be
90                distinct.
91 
92 
93 -Detailed_Output
94 
95    The function returns the index of the highest-indexed element in the
96    input array that is less than or equal to string.  The routine assumes
97    the array elements are sorted in non-decreasing order.
98 
99    If all elements of the input array are greater than the specified
100    upper bound string, the function returns -1.
101 
102 -Parameters
103 
104    None.
105 
106 -Exceptions
107 
108    1) If ndim < 1 the function value is -1.  This is not considered
109       an error.
110 
111    2) If input key value pointer is null, the error SPICE(NULLPOINTER) will
112       be signaled.  The function returns -1.
113 
114    3) The input key value may have length zero.  This case is not
115       considered an error.
116 
117    4) If the input array pointer is null,  the error SPICE(NULLPOINTER) will
118       be signaled.  The function returns -1.
119 
120    5) If the input array string's length is less than 2, the error
121       SPICE(STRINGTOOSHORT) will be signaled.  The function returns -1.
122 
123 -Files
124 
125    None.
126 
127 -Particulars
128 
129    Note:  If you need to find the first element of the array that is
130           greater than string, simply add 1 to the result returned by
131           this function and check to see if the result is within the
132           array bounds given by n.
133 
134 -Examples
135 
136    Let array be a character array of dimension
137 
138       [5][lenvals]
139 
140    which contains the following elements:
141 
142       "BOHR"
143       "EINSTEIN"
144       "FEYNMAN"
145       "GALILEO"
146       "NEWTON"
147 
148    Then
149 
150       lstlec_c ( "NEWTON",   5, lenvals, array )    ==   4
151       lstlec_c ( "EINSTEIN", 5, lenvals, array )    ==   1
152       lstlec_c ( "GALILEO",  5, lenvals, array )    ==   3
153       lstlec_c ( "Galileo",  5, lenvals, array )    ==   3
154       lstlec_c ( "BETHE",    5, lenvals, array )    ==  -1
155 
156 -Restrictions
157 
158    1)  The input array is assumed to be sorted in increasing order. If
159        this condition is not met, the results of bsrchc_c are unpredictable.
160 
161    2)  String comparisons performed by this routine are Fortran-style:
162        trailing blanks in the input array or key value are ignored.
163        This gives consistent behavior with CSPICE code generated by
164        the f2c translator, as well as with the Fortran SPICE Toolkit.
165 
166        Note that this behavior is not identical to that of the ANSI
167        C library functions strcmp and strncmp.
168 
169 -Literature_References
170 
171    None.
172 
173 -Author_and_Institution
174 
175    N.J. Bachman    (JPL)
176    H.A. Neilan     (JPL)
177    W.L. Taber      (JPL)
178 
179 -Version
180 
181    -CSPICE Version 1.0.0, 22-JUL-2002 (NJB) (HAN) (WLT)
182 
183 -Index_Entries
184 
185    last character element less_than_or_equal_to
186 
187 -&
188 */
189 
190 { /* Begin lstlec_c */
191 
192 
193    /*
194    f2c library utility prototypes
195    */
196    logical          l_ge   (char *a, char *b, ftnlen la, ftnlen lb );
197    logical          l_le   (char *a, char *b, ftnlen la, ftnlen lb );
198    logical          l_lt   (char *a, char *b, ftnlen la, ftnlen lb );
199 
200    /*
201    Local macros
202    */
203    #define ARRAY( i )     (  ( (SpiceChar *)array ) + (i)*lenvals  )
204 
205 
206    /*
207    Local variables
208    */
209    SpiceInt                begin;
210    SpiceInt                end;
211    SpiceInt                items;
212    SpiceInt                j;
213    SpiceInt                keylen;
214    SpiceInt                middle;
215 
216 
217 
218    /*
219    Use discovery check-in.
220 
221    Return immediately if the array dimension is non-positive.
222    */
223    if ( n < 1 )
224    {
225       return ( -1 );
226    }
227 
228    /*
229    Make sure the pointer for the key value is non-null
230    and that the length is adequate.
231    */
232    CHKPTR_VAL ( CHK_DISCOVER, "lstlec_c", string, -1 );
233 
234 
235    /*
236    Make sure the pointer for the string array is non-null
237    and that the length lenvals is sufficient.
238    */
239    CHKOSTR_VAL ( CHK_DISCOVER, "lstlec_c", array, lenvals, -1 );
240 
241 
242    /*
243    Return if none of the array's elements are less than or equal to
244    the key value.
245    */
246    keylen = strlen(string);
247 
248    begin  = 0;
249    end    = n - 1;
250 
251    if (  l_lt( ( char * )string,
252                ( char * )ARRAY(begin),
253                ( ftnlen )keylen,
254                ( ftnlen )strlen(ARRAY(begin)) )  )
255    {
256       return ( -1 );
257    }
258 
259 
260    /*
261    Return if the key string is greater than or equal to
262    all of the array's elements.
263    */
264    if (  l_ge( ( char * )string,
265                ( char * )ARRAY(end),
266                ( ftnlen )keylen,
267                ( ftnlen )strlen(ARRAY(end)) )  )
268    {
269       return ( end );
270    }
271 
272 
273    /*
274    Do a binary search for the specified key value.
275 
276    At this point, string is greater than or equal to the first element
277    of array and strictly less than the last element of array.
278    */
279    items  = n;
280 
281    while ( items > 2 )
282    {
283       /*
284       Check the middle element.
285       */
286       j      = items / 2;
287       middle = begin + j;
288 
289 
290       /*
291       Narrow the search area.
292       */
293       if (  l_le ( (char    * ) ARRAY(middle),
294                    (char    * ) string,
295                    (ftnlen    ) lenvals-1,
296                    (ftnlen    ) keylen        )  )
297       {
298          /*
299          The middle element is less than or equal to string.
300          */
301          begin = middle;
302       }
303       else
304       {
305          end   = middle;
306       }
307 
308       items = end - begin + 1;
309 
310       /*
311       At this point, string is greater than or equal to the array element
312       at index begin and strictly less than the element at index end.
313       */
314    }
315 
316    /*
317    The element at index begin is the winner.
318    */
319    return ( begin );
320 
321 
322 } /* End lstlec_c */
323