Skip to main content

rsspice/generated/spicelib/
lparse.rs

1//
2// GENERATED FILE
3//
4
5use super::*;
6use crate::SpiceContext;
7use f2rust_std::*;
8
9const BLANK: &[u8; 1 as usize] = &fstr::extend_const::<{ 1 as usize }>(b" ");
10const ISPACE: i32 = 32;
11
12/// Parse items from a list
13///
14/// Parse a list of items delimited by a single character.
15///
16/// # Brief I/O
17///
18/// ```text
19///  VARIABLE  I/O  DESCRIPTION
20///  --------  ---  --------------------------------------------------
21///  LIST       I   List of items delimited by DELIM.
22///  DELIM      I   Single character used to delimit items.
23///  NMAX       I   Maximum number of items to return.
24///  N          O   Number of items in the list.
25///  ITEMS      O   Items in the list, left justified.
26/// ```
27///
28/// # Detailed Input
29///
30/// ```text
31///  LIST     is a list of items delimited by the single character
32///           DELIM. Consecutive delimiters, and delimiters at the
33///           beginning and end of the list, are considered to
34///           delimit blank items. A blank list is considered to
35///           contain a single (blank) item.
36///
37///  DELIM    is the character delimiting the items in the list.
38///           This may be any ASCII character, including a blank.
39///           However, by definition, consecutive blanks are NOT
40///           considered to be consecutive delimiters. In addition,
41///           leading and trailing blanks are ignored.
42///
43///  NMAX     is the maximum number of items to be returned from
44///           the list. This allows the user to guard against
45///           overflow from a list containing more items than
46///           expected.
47/// ```
48///
49/// # Detailed Output
50///
51/// ```text
52///  N        is the number of items in the list. N may be
53///           any number between one and NMAX. N is always the
54///           number of delimiters plus one.
55///
56///  ITEMS    are the items in the list, left justified. Any item
57///           in the list too long to fit into an element of ITEMS
58///           is truncated on the right.
59/// ```
60///
61/// # Exceptions
62///
63/// ```text
64///  Error free.
65///
66///  1)  If the string length of ITEMS is too short to accommodate
67///      an item, the item will be truncated on the right.
68/// ```
69///
70/// # Examples
71///
72/// ```text
73///  The numerical results shown for these examples may differ across
74///  platforms. The results depend on the SPICE kernels used as
75///  input, the compiler and supporting libraries, and the machine
76///  specific arithmetic implementation.
77///
78///  1) Parse a character string to retrieve the words contained
79///     within.
80///
81///     Example code begins here.
82///
83///
84///           PROGRAM LPARSE_EX1
85///           IMPLICIT NONE
86///
87///     C
88///     C     Local constants.
89///     C
90///           INTEGER                 NMAX
91///           PARAMETER             ( NMAX   = 25  )
92///
93///           INTEGER                 STRLEN
94///           PARAMETER             ( STRLEN = 255 )
95///
96///     C
97///     C     Local variables.
98///     C
99///           CHARACTER*(1)           DELIM
100///           CHARACTER*(STRLEN)      ITEMS  ( NMAX )
101///           CHARACTER*(STRLEN)      LIST
102///
103///           INTEGER                 I
104///           INTEGER                 N
105///
106///     C
107///     C     Define the list of delimited items.
108///     C
109///     C     Think of a sentence as a list delimited by a space.
110///     C     DELIM is assigned to a space.
111///     C
112///           LIST  = 'Run and find out.'
113///           DELIM = ' '
114///
115///     C
116///     C     Parse the items from LIST.
117///     C
118///           CALL LPARSE ( LIST, DELIM, NMAX, N, ITEMS )
119///
120///     C
121///     C     Output the ITEMS.
122///     C
123///           DO I = 1, N
124///
125///              WRITE(*,'(A,I3,2A)') 'Item', I, ': ', ITEMS(I)
126///
127///           END DO
128///
129///           END
130///
131///
132///     When this program was executed on a Mac/Intel/gfortran/64-bit
133///     platform, the output was:
134///
135///
136///     Item  1: Run
137///     Item  2: and
138///     Item  3: find
139///     Item  4: out.
140///
141///
142///  2) Repeat the previous example with different character
143///     delimiting the items in the list and different maximum number
144///     of items to return.
145///
146///     Example code begins here.
147///
148///
149///           PROGRAM LPARSE_EX2
150///           IMPLICIT NONE
151///
152///     C
153///     C     SPICELIB functions.
154///     C
155///           INTEGER                 RTRIM
156///
157///     C
158///     C     Local constants.
159///     C
160///           INTEGER                 NCASES
161///           PARAMETER             ( NCASES = 2   )
162///
163///           INTEGER                 NMAXT
164///           PARAMETER             ( NMAXT  = 25  )
165///
166///           INTEGER                 STRLEN
167///           PARAMETER             ( STRLEN = 255 )
168///
169///     C
170///     C     Local variables.
171///     C
172///           CHARACTER*(1)           DELIM  ( NCASES )
173///           CHARACTER*(STRLEN)      ITEMS  ( NMAXT  )
174///           CHARACTER*(STRLEN)      LIST   ( NCASES )
175///
176///           INTEGER                 I
177///           INTEGER                 J
178///           INTEGER                 N
179///           INTEGER                 NMAX   ( NCASES )
180///
181///     C
182///     C     Define the lists of delimited items, the delimiting
183///     C     character and the maximum number of items to return.
184///     C
185///           LIST(1)  = '//option1//option2/ //'
186///           DELIM(1) = '/'
187///           NMAX(1)  = 20
188///
189///           LIST(2)  = ' ,bob,   carol,, ted,  alice'
190///           DELIM(2) = ','
191///           NMAX(2)  = 4
192///
193///           DO I = 1, NCASES
194///
195///              WRITE(*,'(A,I2,A)') 'Case', I, ':'
196///              WRITE(*,'(3A)')   '   String: ''',
197///          .                     LIST(I)(:RTRIM(LIST(I))), ''''
198///              WRITE(*,'(3A)')   '   DELIM : ''', DELIM(I), ''''
199///              WRITE(*,'(A,I3)') '   NMAX  :', NMAX(I)
200///              WRITE(*,'(A)')    '   Output items:'
201///
202///     C
203///     C        Parse the items from LIST.
204///     C
205///              CALL LPARSE ( LIST(I), DELIM(I), NMAX(I), N, ITEMS )
206///
207///     C
208///     C        Output the ITEMS.
209///     C
210///              DO J = 1, N
211///
212///                 WRITE(*,'(A,I3,3A)') '      Item', J, ': ''',
213///          .                  ITEMS(J)(:RTRIM(ITEMS(J))), ''''
214///
215///              END DO
216///
217///           END DO
218///
219///           END
220///
221///
222///     When this program was executed on a Mac/Intel/gfortran/64-bit
223///     platform, the output was:
224///
225///
226///     Case 1:
227///        String: '//option1//option2/ //'
228///        DELIM : '/'
229///        NMAX  : 20
230///        Output items:
231///           Item  1: ' '
232///           Item  2: ' '
233///           Item  3: 'option1'
234///           Item  4: ' '
235///           Item  5: 'option2'
236///           Item  6: ' '
237///           Item  7: ' '
238///           Item  8: ' '
239///     Case 2:
240///        String: ' ,bob,   carol,, ted,  alice'
241///        DELIM : ','
242///        NMAX  :  4
243///        Output items:
244///           Item  1: ' '
245///           Item  2: 'bob'
246///           Item  3: 'carol'
247///           Item  4: ' '
248/// ```
249///
250/// # Author and Institution
251///
252/// ```text
253///  N.J. Bachman       (JPL)
254///  J. Diaz del Rio    (ODC Space)
255///  H.A. Neilan        (JPL)
256///  W.L. Taber         (JPL)
257///  I.M. Underwood     (JPL)
258/// ```
259///
260/// # Version
261///
262/// ```text
263/// -    SPICELIB Version 1.2.0, 06-JUL-2021 (JDR)
264///
265///         Added IMPLICIT NONE statement.
266///
267///         Edited the header to comply with NAIF standard. Removed
268///         unnecessary entries from $Revisions section.
269///
270///         Added complete code example.
271///
272/// -    SPICELIB Version 1.1.0, 26-OCT-2005 (NJB)
273///
274///         Bug fix: code was modified to avoid out-of-range
275///         substring bound conditions.
276///
277/// -    SPICELIB Version 1.0.1, 10-MAR-1992 (WLT)
278///
279///         Comment section for permuted index source lines was added
280///         following the header.
281///
282/// -    SPICELIB Version 1.0.0, 31-JAN-1990 (IMU) (HAN) (NJB)
283/// ```
284///
285/// # Revisions
286///
287/// ```text
288/// -    SPICELIB Version 1.1.0, 26-OCT-2005 (NJB)
289///
290///         Bug fix: code was modified to avoid out-of-range
291///         substring bound conditions. The previous version
292///         of this routine used DO WHILE statements of the form
293///
294///                   DO WHILE (      ( B         .LE. EOL   )
295///            .                .AND. ( LIST(B:B) .EQ. BLANK ) )
296///
297///         Such statements can cause index range violations when the
298///         index B is greater than the length of the string LIST.
299///         Whether or not such violations occur is platform-dependent.
300/// ```
301pub fn lparse(list: &str, delim: char, nmax: i32, n: &mut i32, items: CharArrayMut) {
302    LPARSE(
303        list.as_bytes(),
304        &[u8::try_from(delim).unwrap()],
305        nmax,
306        n,
307        items,
308    );
309}
310
311//$Procedure LPARSE ( Parse items from a list )
312pub fn LPARSE(LIST: &[u8], DELIM: &[u8], NMAX: i32, N: &mut i32, ITEMS: CharArrayMut) {
313    let DELIM = &DELIM[..1 as usize];
314    let mut ITEMS = DummyCharArrayMut::new(ITEMS, None, 1..);
315    let mut BCHR = [b' '; 1 as usize];
316    let mut ECHR = [b' '; 1 as usize];
317    let mut B: i32 = 0;
318    let mut E: i32 = 0;
319    let mut EOL: i32 = 0;
320
321    //
322    // Local parameters
323    //
324
325    //
326    // Local variables
327    //
328
329    //
330    // Because speed is essential in many list parsing applications,
331    // LPARSE parses the input list in a single pass.
332    //
333
334    //
335    // Nothing yet.
336    //
337    *N = 0;
338
339    //
340    // Blank list contains a blank item.
341    //
342    if fstr::eq(LIST, BLANK) {
343        *N = 1;
344        fstr::assign(ITEMS.get_mut(1), BLANK);
345    } else {
346        //
347        // Eliminate trailing blanks. EOL is the last non-blank
348        // character in the list.
349        //
350        EOL = intrinsics::LEN(LIST);
351
352        while fstr::eq(fstr::substr(LIST, EOL..=EOL), BLANK) {
353            EOL = (EOL - 1);
354        }
355
356        //
357        // As the king said to Alice: 'Begin at the beginning.
358        // Continue until you reach the end. Then stop.'
359        //
360        // When searching for items, B is the beginning of the current
361        // item; E is the end.  E points to the next non-blank delimiter,
362        // if any; otherwise E points to either the last character
363        // preceding the next item, or to the last character of the list.
364        //
365        B = 1;
366
367        while (B <= EOL) {
368            //
369            // Skip any blanks before the next item or delimiter.
370            //
371            // At this point in the loop, we know
372            //
373            //    B <= EOL
374            //
375            fstr::assign(&mut BCHR, fstr::substr(LIST, B..=B));
376
377            while ((B <= EOL) && (intrinsics::ICHAR(&BCHR) == ISPACE)) {
378                B = (B + 1);
379
380                if (B <= EOL) {
381                    fstr::assign(&mut BCHR, fstr::substr(LIST, B..=B));
382                }
383            }
384
385            //
386            // At this point B is the index of the next non-blank
387            // character BCHR, or else
388            //
389            //    B == EOL + 1
390            //
391            // The item ends at the next delimiter.
392            //
393            E = B;
394
395            if (E <= EOL) {
396                fstr::assign(&mut ECHR, fstr::substr(LIST, E..=E));
397            } else {
398                fstr::assign(&mut ECHR, BLANK);
399            }
400
401            while ((E <= EOL) && fstr::ne(&ECHR, DELIM)) {
402                E = (E + 1);
403
404                if (E <= EOL) {
405                    fstr::assign(&mut ECHR, fstr::substr(LIST, E..=E));
406                }
407            }
408
409            //
410            // The item now lies between B and E. Unless, of course, B and
411            // E are the same character; this can happen if the list
412            // starts or ends with a non-blank delimiter, or if we have
413            // stumbled upon consecutive delimiters.
414            //
415            *N = (*N + 1);
416
417            if (E > B) {
418                fstr::assign(ITEMS.get_mut(*N), fstr::substr(LIST, B..=(E - 1)));
419            } else {
420                fstr::assign(ITEMS.get_mut(*N), BLANK);
421            }
422
423            //
424            // If there are more items to be found, continue with
425            // character following E (which is a delimiter).
426            //
427            if (*N < NMAX) {
428                B = (E + 1);
429            } else {
430                return;
431            }
432        }
433
434        //
435        // If the list ended with a (non-blank) delimiter, add a blank
436        // item to the end.
437        //
438        if (fstr::eq(fstr::substr(LIST, EOL..=EOL), DELIM) && (*N < NMAX)) {
439            *N = (*N + 1);
440            fstr::assign(ITEMS.get_mut(*N), BLANK);
441        }
442    }
443}