Bioplib
Protein Structure C Library
 All Data Structures Files Functions Variables Typedefs Macros Pages
fsscanf.c
Go to the documentation of this file.
1 /************************************************************************/
2 /**
3 
4  \file fsscanf.c
5 
6  \version V1.4
7  \date 07.07.14
8  \brief Read from a string using FORTRAN-like rigid formatting
9 
10  \copyright (c) UCL / Dr. Andrew C. R. Martin 1993-2014
11  \author Dr. Andrew C. R. Martin
12  \par
13  Institute of Structural & Molecular Biology,
14  University College London,
15  Gower Street,
16  London.
17  WC1E 6BT.
18  \par
19  andrew@bioinf.org.uk
20  andrew.martin@ucl.ac.uk
21 
22 **************************************************************************
23 
24  This code is NOT IN THE PUBLIC DOMAIN, but it may be copied
25  according to the conditions laid out in the accompanying file
26  COPYING.DOC.
27 
28  The code may be modified as required, but any modifications must be
29  documented so that the person responsible can be identified.
30 
31  The code may not be sold commercially or included as part of a
32  commercial product except as described in the file COPYING.DOC.
33 
34 **************************************************************************
35 
36  Description:
37  ============
38 
39  Hard formatted version of sscanf(). Implements FORTRAN-like file
40  reading.
41 
42  The only parsing characters recognised are:
43 
44 
45  %<n>f A single precision floating point number of width <n>
46  %<n>lf A double precision floating point number of width <n>
47  %<n>d An integer of width <n>
48  %<n>ld A long integer of width <n>
49  %<n>u An unsigned of width <n>
50  %<n>lu An unsigned long of width <n>
51  %<n>s A string of width <n>
52  %c A character (of width 1)
53  %<n>x <n> spaces (like FORTRAN).
54 
55  With the exception of the %c parser, the column width, <n>,
56  *must* be specified.
57 
58  Blank fields read as numbers are given a value of zero.
59 
60  Returns: The number of arguments filled in (EOF if blank string or no
61  specifiers found in format string).
62 
63 **************************************************************************
64 
65  Usage:
66  ======
67  For example:
68 
69 \code
70  double DoubVar;
71  int IntVar;
72  char CharVar,
73  StringVar[16];
74 
75  fsscanf(buffer,"%8lf%5x%3d%c%3x%8s",
76  &DoubVar,&IntVar,&CharVar,StringVar);
77 \endcode
78 
79 **************************************************************************
80 
81  Revision History:
82  =================
83 - V1.0 17.06.93 Original By: ACRM
84 - V1.1 12.07.93 Added %u and %lu. Corrected %s and %c to blank rather
85  than NULL strings if buffer runs out. Pads string if
86  buffer ran out in the middle. Takes \n in buffer as end
87  of string.
88 - V1.2 24.11.95 `value' was a fixed 40 character buffer. Now changed to
89  allocate a suitable number of characters as required.
90 - V1.3 13.01.97 Now does the EOF return at the end of the routine
91  rather than at the beginning so that all the variable
92  get set to blank or zero first.
93 - V1.4 07.07.14 Use bl prefix for functions By: CTP
94 
95 *************************************************************************/
96 /* Doxygen
97  -------
98  #GROUP General Programming
99  #SUBGROUP File IO
100  #FUNCTION fsscanf()
101  A FORTRAN-style rigid-column formatted version of sscanf()
102 */
103 
104 /************************************************************************/
105 /* Includes
106 */
107 #include <stdio.h>
108 #include <string.h>
109 #include <stdarg.h>
110 #include <stdlib.h>
111 #include <ctype.h>
112 
113 #include "SysDefs.h"
114 #include "macros.h"
115 #include "general.h"
116 
117 /************************************************************************/
118 /* Defines and macros
119 */
120 
121 /************************************************************************/
122 /* Globals
123 */
124 
125 /************************************************************************/
126 /* Prototypes
127 */
128 
129 /************************************************************************/
130 /*>int fsscanf(char *buffer, char *format, ...)
131  --------------------------------------------
132 *//**
133 
134  \param[in] *buffer Buffer from which to read information
135  \param[in] *format Format string (like scanf() et al., but see
136  restrictions below)
137  \param[out] ... Scanned output variables
138  \return Number of values read (EOF if end of file or
139  no specifiers found in format string)
140 
141  Hard formatted version of sscanf(). Implements FORTRAN-like rigid
142  column reading out of a string.
143 
144  The only parsing characters recognised are:
145 
146 
147  %<n>f A single precision floating point number of width <n>
148  %<n>lf A double precision floating point number of width <n>
149  %<n>d An integer of width <n>
150  %<n>ld A long integer of width <n>
151  %<n>u An unsigned of width <n>
152  %<n>lu An unsigned long of width <n>
153  %<n>s A string of width <n>
154  %c A character (of width 1)
155  %<n>x <n> spaces (like FORTRAN).
156 
157  With the exception of the %c parser, the column width, <n>,
158  *must* be specified.
159 
160  Blank fields read as numbers are given a value of zero.
161 
162 
163 - 17.06.93 Original By: ACRM
164 - 12.07.93 Added %u and %lu. Corrected %s and %c to blank rather than
165  NULL strings if buffer runs out. Pads string if buffer ran
166  out in the middle. Takes \n in buffer as end of string.
167 - 24.11.95 `value' was a fixed 40 character buffer. Now changed to
168  allocate a suitable number of characters as required.
169 - 13.01.97 Previously if reading from a blank line the output variables
170  were unmodified since an EOF return was done immediately.
171  Now the immediate EOF return only happens if the input
172  buffer is a NULL variable and the EOF on blank string is
173  moved to the end such that all output variables are set to
174  zero or blank before the EOF return.
175 - 07.07.14 Use bl prefix for functions By: CTP
176 */
177 int fsscanf(char *buffer, char *format, ...)
178 {
179  va_list ap;
180  char *FormStart,
181  *BuffStart,
182  *stop,
183  form[16], /* Store a single formatting code */
184  *value = NULL, /* Store an item */
185  *ptr,
186  type;
187  int i,
188  MaxValLength = 40, /* Initial max value width */
189  *IntPtr,
190  NArg = 0,
191  width = 0;
192  BOOL LongType = FALSE;
193  double *DblPtr;
194  float *FloatPtr;
195  long *LongPtr;
196  unsigned *UPtr;
197  unsigned long *ULongPtr;
198 
199  /* Return if line is blank */
200  if(!buffer) return(EOF);
201 
202  /* Allocate initial memory for storing a value */
203  if((value=(char *)malloc((1+MaxValLength)*sizeof(char)))==NULL)
204  return(0);
205 
206  /* Start the variable argument processing */
207  va_start(ap, format);
208 
209  /* Intialise FormStart to the start of the format string and BuffStart
210  to start of input buffer
211  */
212  FormStart = format;
213  BuffStart = buffer;
214 
215  for(;;)
216  {
217  /* Flag for long variables */
218  LongType = FALSE;
219 
220  /* Find the start of a % group from the format string */
221  while(*FormStart && *FormStart != '%') FormStart++;
222  if(!(*FormStart)) break; /* Exit routine */
223 
224  /* Find the next occurence of a % */
225  stop = FormStart+1;
226  while(*stop && *stop != '%') stop++;
227 
228  /* Copy these format characters into our working buffer */
229  for(i=0; FormStart != stop; i++)
230  form[i] = *(FormStart++);
231  form[i] = '\0';
232 
233  /* Find the type we're dealing with */
234  ptr = form + i;
235  while(*ptr == '\0' || *ptr == ' ' || *ptr == '\t') ptr--;
236  type = toupper(*ptr);
237 
238  /* Set long flag if appropriate */
239  if((*(ptr-1) == 'l') || (*(ptr-1) == 'L'))
240  LongType = TRUE;
241 
242  /* If it's not a character, read the width from the form string */
243  width = 0;
244  if(type == 'C')
245  {
246  width = 1;
247  }
248  else
249  {
250  for(ptr = form+1; *ptr && isdigit(*ptr); ptr++)
251  {
252  width *= 10;
253  width += (*ptr) - '0';
254  }
255  }
256 
257  /* See if our buffer is wide enough for this item. If not, make
258  more space
259  */
260  if(width > MaxValLength)
261  {
262  if((value = (char *)realloc(value, (width+1) * sizeof(char)))
263  ==NULL)
264  {
265  /* Unable to do allocation */
266  va_end(ap);
267  return(0);
268  }
269  MaxValLength = width;
270  }
271 
272 
273  /* Extract width characters from the input buffer. If the input
274  buffer has run out, value will be a NULL string.
275  */
276  stop = BuffStart + width;
277  for(i=0; *BuffStart && *BuffStart != '\n' && BuffStart != stop; i++)
278  value[i] = *(BuffStart++);
279  value[i] = '\0';
280 
281  /* Act on each type */
282  switch(type)
283  {
284  case 'F': /* A double precision or float */
285  if(LongType)
286  {
287  DblPtr = va_arg(ap, double *);
288  if(sscanf(value,"%lf", DblPtr) == (-1))
289  *DblPtr = (double)0.0;
290  }
291  else
292  {
293  FloatPtr = va_arg(ap, float *);
294  if(sscanf(value,"%f", FloatPtr) == (-1))
295  *FloatPtr = (float)0.0;
296  }
297 
298  break;
299  case 'D': /* An integer or long int */
300  if(LongType)
301  {
302  LongPtr = va_arg(ap, long *);
303  if(sscanf(value,"%ld", LongPtr) == (-1))
304  *LongPtr = 0L;
305  }
306  else
307  {
308  IntPtr = va_arg(ap, int *);
309  if(sscanf(value,"%d", IntPtr) == (-1))
310  *IntPtr = 0;
311  }
312  break;
313  case 'U': /* An unsigned or unsigned long */
314  if(LongType)
315  {
316  ULongPtr = va_arg(ap, unsigned long *);
317  if(sscanf(value,"%lu", ULongPtr) == (-1))
318  *ULongPtr = 0L;
319  }
320  else
321  {
322  UPtr = va_arg(ap, unsigned *);
323  if(sscanf(value,"%u", UPtr) == (-1))
324  *UPtr = 0;
325  }
326  break;
327  case 'S': /* A string */
328  ptr = va_arg(ap, char *);
329  if(value[0]) /* Input buffer not empty */
330  {
331  *(value + width) = '\0';
332  strncpy(ptr, value, width+1);
333 
334  /* If the input buffer ran out in this string, pad with
335  spaces and terminate.
336  */
337  if(strlen(ptr) < width) blPadterm(ptr, width);
338  }
339  else /* Input buffer empty */
340  {
341  for(i=0; i<width; i++)
342  *(ptr + i) = ' ';
343  *(ptr + width) = '\0';
344  }
345  break;
346  case 'C': /* A character (insert a space if buffer empty) */
347  *(va_arg(ap, char *)) = (value[0] ? value[0]: ' ');
348  break;
349  case 'X': /* A column to skip */
350  /* Fall through to default action */
351  default:
352  /* Do nothing */
353  ;
354  }
355 
356  /* If not a blank column, increment arg count */
357  if(type != 'X') NArg++;
358 
359  }
360 
361  /* End variable argument parsing */
362  va_end(ap);
363 
364  /* Free the allocated buffer */
365  free(value);
366 
367  /* Return number of values read or EOF if it was a blank input */
368  if(buffer[0] == '\0' || buffer[0] == '\n') return(EOF);
369  return(NArg);
370 }
short BOOL
Definition: SysDefs.h:64
#define NULL
Definition: array2.c:99
void blPadterm(char *string, int length)
Definition: padterm.c:117
#define FALSE
Definition: macros.h:223
Useful macros.
int fsscanf(char *buffer, char *format,...)
Definition: fsscanf.c:177
#define TRUE
Definition: macros.h:219
Header file for general purpose routines.
System-type variable type definitions.