1 /*
2 
3 -Procedure eqstr_c ( Equivalent strings )
4 
5 -Abstract
6 
7    Determine whether two strings are equivalent.
8 
9 -Disclaimer
10 
11    THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE
12    CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S.
13    GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE
14    ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE
15    PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS"
16    TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY
17    WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A
18    PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC
19    SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE
20    SOFTWARE AND RELATED MATERIALS, HOWEVER USED.
21 
22    IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA
23    BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT
24    LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND,
25    INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS,
26    REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE
27    REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY.
28 
29    RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF
30    THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY
31    CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE
32    ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE.
33 
34 -Required_Reading
35 
36    None.
37 
38 -Keywords
39 
40    ALPHANUMERIC
41    ASCII
42    CHARACTER
43    COMPARE
44    PARSING
45    SEARCH
46    STRING
47    TEXT
48 
49 */
50    #include <ctype.h>
51    #include "SpiceUsr.h"
52    #include "SpiceZmc.h"
53 
54 
eqstr_c(ConstSpiceChar * a,ConstSpiceChar * b)55    SpiceBoolean eqstr_c ( ConstSpiceChar * a,  ConstSpiceChar * b )
56 
57 /*
58 
59 -Brief_I/O
60 
61    VARIABLE  I/O  DESCRIPTION
62    --------  ---  --------------------------------------------------
63    a,
64    b          I   Arbitrary character strings.
65 
66    The function returns SPICETRUE if A and B are equivalent.
67 
68 -Detailed_Input
69 
70    a,
71    b           are arbitrary character strings.
72 
73 -Detailed_Output
74 
75    The function returns TRUE if A and B are equivalent: that is,
76    if A and B contain  the same characters in the same order,
77    when white space characters are ignored and uppercase and lowercase
78    characters are considered equal.
79 
80    White space characters are those in the set
81 
82       { ' ', '\f', '\n', '\r', '\t', '\v' }
83 
84    Note that this specification differs from that of the Fortran version
85    of this routine, which considers the blank ( ' ' ) to be the only
86    white space character.
87 
88 -Parameters
89 
90    None.
91 
92 -Files
93 
94    None.
95 
96 -Exceptions
97 
98     1) If either input string pointer is null, the error
99        SPICE(NULLPOINTER) will be signaled.
100 
101 
102 -Particulars
103 
104    This routine is provided for those cases in which two strings
105    must be compared, and in which allowances are to be made for
106    extra (leading, trailing, and embedded) blanks and differences
107    in case. For the most part,
108 
109       if ( eqstr_c ( A, B ) )
110          .
111          .
112 
113    is true whenever
114 
115       cmprss_c ( ' ', 0, a,        MAXLEN, tempa );
116       ucase_c  (            tempa, MAXLEN, tempa );
117 
118       cmprss_c ( ' ', 0, b,        MAXLEN, tempb );
119       ucase_c  (            tempb, MAXLEN, tempb );
120 
121 
122       if ( !strcmp ( tempa, tempb ) )
123          .
124          .
125 
126    is true. There are two important differences, however.
127 
128       1) The single reference to eqstr_c is much simpler to
129          write, and simpler to understand.
130 
131       2) The reference to eqstr_c does not require any temporary
132          storage, nor does it require that the strings a and b
133          be changed. This feature is especially useful when
134          comparing strings recieved as subprogram arguments
135          against strings stored internally within the subprogram.
136 
137 
138 -Examples
139 
140 
141     Usage
142     --------------------------------------------
143 
144        All of the following are TRUE.
145 
146           eqstr_c ( "A short string   ",
147                     "ashortstring"        );
148 
149           eqstr_c ( "Embedded        blanks",
150                     "Em be dd ed bl an ks"    );
151 
152           eqstr_c ( "Embedded        blanks",
153                     "   Embeddedblanks"    );
154 
155           eqstr_c ( " ",
156                     "          " );
157 
158 
159        All of the following are FALSE.
160 
161           eqstr_c ( "One word left out",
162                     "WORD LEFT OUT"      );
163 
164           eqstr_c ( "Extra [] delimiters",
165                     "extradelimiters"      );
166 
167           eqstr_c ( "Testing 1, 2, 3",
168                     "TESTING123"       );
169 
170 
171     Use
172     --------------------------------------------
173 
174        The following illustrates a typical use for eqstr_c.
175 
176           #include "SpiceUsr.h"
177               .
178               .
179               .
180           SpiceChar * greeting ( SpiceChar *who )
181           {
182 
183              if ( eqstr_c ( who, "Steve" ) )
184              {
185                 return ( "Yes, sir?" );
186              }
187              else if ( eqstr_c ( who, "Chuck" ) )
188              {
189                 return ( "What can I do for you?" );
190              }
191              else
192              {
193                 return ( "Whaddya want?" );
194              }
195           }
196 
197        Note that all of the following calls will elicit the
198        greeting "Yes, sir?":
199 
200           greeting ( "STEVE" );
201           greeting ( "steve" );
202           greeting ( "Steve" );
203           greeting ( "sTEVE" );
204           greeting ( " S T E V E " );
205 
206 -Restrictions
207 
208    None.
209 
210 -Literature_References
211 
212    1)  "American National Standard for Programming Languages -- C,"
213         Published by the American National Standards Institute, 1990.
214         Section 7.3.1.9., p. 104.
215 
216 -Author_and_Institution
217 
218    N.J. Bachman    (JPL)
219    I.M. Underwood  (JPL)
220 
221 -Version
222 
223    -CSPICE Version 1.3.0, 27-AUG-1999   (NJB)
224 
225       Added check for null input strings.  Added logic to handle the
226       case where at least one input string is empty.
227 
228    -CSPICE Version 1.2.0, 24-FEB-1999 (NJB)
229 
230        Arguments passed to isspace are now cast to unsigned char to
231        suppress compilation warnings on some systems.
232 
233    -CSPICE Version 1.1.0, 08-FEB-1998 (NJB)
234 
235        Initial assignment of return value added to suppress compilation
236        warnings on some systems.
237 
238    -CSPICE Version 1.0.0, 25-OCT-1997 (NJB)
239 
240        Based on SPICELIB Version 1.2.0, 03-AUG-1994 (NJB)
241 
242 -Index_Entries
243 
244    equivalent strings
245 
246 -&
247 */
248 
249 { /* Begin eqstr_c */
250 
251    /*
252    Local constants
253    */
254    #define  LBOUND     (   (SpiceInt) 'a'            )
255    #define  UBOUND     (   (SpiceInt) 'z'            )
256    #define  DELTA      ( ( (SpiceInt) 'A' ) - LBOUND )
257 
258 
259    /*
260    Local variables
261    */
262    SpiceBoolean            done;
263    SpiceBoolean            retval;
264 
265    ConstSpiceChar         * pa;
266    ConstSpiceChar         * pb;
267 
268    SpiceInt                ca;
269    SpiceInt                cb;
270 
271    SpiceInt                lenA;
272    SpiceInt                lenB;
273 
274 
275    /*
276    Initialize the return value retval in order to make certain
277    compilers happy.  This initial value is not used later; retval
278    is set explicitly in each case below.
279    */
280    retval = SPICEFALSE;
281 
282 
283    /*
284    Check the input string pointers to make sure they're non-null.
285    */
286    CHKPTR_VAL ( CHK_DISCOVER, "eqstr_c", a, retval );
287    CHKPTR_VAL ( CHK_DISCOVER, "eqstr_c", b, retval );
288 
289 
290    /*
291    The general plan is to move a pair of pointers (PA, PB)
292    through strings A and B, skipping blank characters and
293    comparing others one-for-one.
294 
295       Repeat:
296 
297          If (A is blank) then
298             Increment A
299 
300          Else if (B is blank) then
301             Increment B
302 
303          Else
304             If (A and B are equivalent) then
305                Increment A and B
306             Else
307                Return FALSE
308 
309          If (A and B are past end) then
310             Return TRUE
311 
312          Else if (A or B is past end and other is non-blank) then
313             Return FALSE
314 
315          Else if (A or B is past end and other is blank) then
316             Return TRUE
317 
318    Note that no pointer gets incremented more than once on each
319    pass through the loop.
320 
321    On the other hand, in many cases the strings will be exactly
322    equal. If so, why knock ourselves out?
323    */
324 
325    if ( !strcmp( a, b ) )
326    {
327       return ( SPICETRUE );
328    }
329 
330    pa    =  a;
331    pb    =  b;
332    lenA  =  strlen(a);
333    lenB  =  strlen(b);
334 
335 
336    /*
337    The possibility of an input string being empty does not occur in
338    Fortran, but it does here.  Handle these cases (the case where both
339    are empty was handled by the strcmp test above).
340    */
341 
342    if (  ( lenA == 0 ) && ( lenB > 0 )  )
343    {
344       return ( SPICEFALSE );
345    }
346 
347    if (  ( lenB == 0 ) && ( lenA > 0 )  )
348    {
349       return ( SPICEFALSE );
350    }
351 
352 
353    /*
354    On with the normal path.
355    */
356 
357    done  =  SPICEFALSE;
358 
359 
360    while ( !done )
361    {
362 
363       /*
364       At this point, we're guaranteed that strings a and b have more
365       characters to examine, that is:
366 
367         ( pa <= a+lenA-1 )   and   ( pb <= b+lenB-1 )
368 
369       */
370 
371 
372       if (  isspace( (unsigned char) *pa )  )
373       {
374          pa++;
375       }
376       else if (  isspace( (unsigned char) *pb)  )
377       {
378          pb++;
379       }
380       else
381       {
382 
383          ca = (SpiceInt)(*pa);
384          cb = (SpiceInt)(*pb);
385 
386          if ( ( ca >= LBOUND ) && ( ca <= UBOUND ) )
387          {
388             ca = ca + DELTA;
389          }
390 
391          if ( ( cb >= LBOUND ) && ( cb <= UBOUND ) )
392          {
393             cb = cb + DELTA;
394          }
395 
396          if ( ca == cb )
397          {
398             pa++;
399             pb++;
400          }
401          else
402          {
403             /*
404             We now know the strings don't match.
405             */
406             retval = SPICEFALSE;
407             done   = SPICETRUE;
408          }
409       }
410 
411       if ( !done )
412       {
413          /*
414          At this point, the strings still match and we've advanced
415          at least one of the pointers.
416          */
417 
418 
419          if (  ( (SpiceInt)(pa-a) )  ==  lenA  )
420          {
421             /*
422             There are no more characters in string a to examine.  The
423             rest of string b had better be white space, or else we had
424             better be at the end of string b.
425             */
426 
427             if ( ( (SpiceInt)(pb-b) )  ==  lenB  )
428             {
429                /*
430                We've seen all of string b.
431                */
432 
433                retval = SPICETRUE;
434                done   = SPICETRUE;
435             }
436             else if ( iswhsp_c(pb) )
437             {
438                retval = SPICETRUE;
439                done   = SPICETRUE;
440             }
441             else
442             {
443                retval = SPICEFALSE;
444                done   = SPICETRUE;
445             }
446          }
447          /*
448          End of "no more characters in string a" case.
449          */
450 
451          else if (  ( (SpiceInt)(pb-b) )  ==  lenB  )
452          {
453             /*
454             There are no more characters in string b to examine.  The
455             rest of string a had better be white space.
456             */
457             if ( iswhsp_c(pa) )
458             {
459                retval = SPICETRUE;
460                done   = SPICETRUE;
461             }
462             else
463             {
464                retval = SPICEFALSE;
465                done   = SPICETRUE;
466             }
467          }
468 
469          /*
470          End of "no more characters in string b" case.
471          */
472       }
473       /*
474       At this point, we've handled the cases where at least one
475       string is out of characters.  If such a case occurred, done
476       has been set to SPICETRUE.
477       */
478 
479    }
480    /*
481    End of while loop. retval has been set.
482    */
483 
484    return (retval);
485 
486 
487 } /* End eqstr_c */
488