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}