FreeBASIC  0.91.0
file_lineinp.c
Go to the documentation of this file.
1 /* line input function */
2 
3 #include "fb.h"
4 
5 #define BUFFER_LEN 1024
6 
7 typedef enum _eInputMode {
11 } eInputMode;
12 
13 static int fb_hFileLineInputEx
14  (
15  FB_FILE *handle,
16  void *dst,
17  ssize_t dst_len,
18  int fillrem
19  )
20 {
21  ssize_t len, readlen;
22  char buffer[BUFFER_LEN];
23  eInputMode mode = eIM_Invalid;
24 
25  if( !FB_HANDLE_USED(handle) )
27 
28  FB_LOCK();
29 
30  if( handle->hooks->pfnReadLine != NULL ) {
31  mode = eIM_ReadLine;
32  } else if( handle->hooks->pfnRead != NULL &&
33  handle->hooks->pfnEof != NULL )
34  {
35  mode = eIM_Read;
36  }
37 
38  if( mode==eIM_Invalid ) {
39  FB_UNLOCK();
41  }
42 
43  switch( mode ) {
44  case eIM_Read:
45  /* This is the VFS-compatible way to read a line ... but it's slow */
46  len = readlen = 0;
47  while (!handle->hooks->pfnEof(handle)) {
48  int do_add = FALSE, do_break = FALSE;
49  size_t read_len;
50  int res = fb_FileGetDataEx( handle, 0, buffer+len, 1, &read_len, FALSE, FALSE );
51  if( res==FB_RTERROR_OK && read_len==1) {
52  char ch = buffer[len];
53  if( ch==13 ) {
54  res = fb_FileGetDataEx( handle, 0, &ch, 1, &read_len, FALSE, FALSE );
55  if( res==FB_RTERROR_OK && ch!=10 && read_len==1) {
56  fb_FilePutBackEx( handle, &ch, 1 );
57  }
58  ch = 10;
59  }
60  if( ch==10 ) {
61  do_add = do_break = TRUE;
62  } else {
63  do_add = len==(sizeof(buffer)-1);
64  }
65  } else {
66  do_add = len!=0;
67  }
68  if( do_add || handle->hooks->pfnEof( handle ) ) {
69  /* create temporary string to ensure that NUL's are preserved ...
70  * this function wants the length WITH the NUL character!!! */
71  buffer[len] = 0;
72  FBSTRING *src = fb_StrAllocTempDescF( buffer, len + 1);
73  if( readlen==0 ) {
74  fb_StrAssign( dst, dst_len, src, -1, fillrem );
75  } else {
76  fb_StrConcatAssign ( dst, dst_len, src, -1, fillrem );
77  }
78  readlen += len;
79  len = 0;
80  } else {
81  ++len;
82  }
83  if( res!=FB_RTERROR_OK || do_break )
84  break;
85  }
86  if( readlen == 0 ) {
87  /* del destine string */
88  if( dst_len == -1 )
89  fb_StrDelete( (FBSTRING *)dst );
90  else
91  *(char *)dst = '\0';
92  }
93  break;
94  case eIM_ReadLine:
95  /* The read line mode is the most comfortable ... but IMHO it's
96  * only useful for special devices (like SCRN:) */
97  {
98  /* destine is a var-len string? read directly */
99  if( dst_len == -1 )
100  {
101  handle->hooks->pfnReadLine( handle, dst );
102  }
103  /* fixed-len or unknown size (ie: pointers)? use a temp var-len */
104  else
105  {
106  FBSTRING str_result = { 0 };
107 
108  /* read complete line (may include NULs) */
109  handle->hooks->pfnReadLine( handle, &str_result );
110 
111  /* add contents of tempporary string to result buffer */
112  fb_StrAssign( dst, dst_len, (void *)&str_result, -1, fillrem );
113 
114  /* delete result */
115  fb_StrDelete( &str_result );
116  }
117 
118  }
119  break;
120  case eIM_Invalid:
121  /* the "invalid" mode was already handled above ... so we don't
122  * need to do anything here ... */
123  break;
124  }
125 
126  FB_UNLOCK();
127 
128  return fb_ErrorSetNum( FB_RTERROR_OK );
129 }
130 
131 FBCALL int fb_FileLineInput( int fnum, void *dst, ssize_t dst_len, int fillrem )
132 {
133  return fb_hFileLineInputEx( FB_FILE_TO_HANDLE(fnum), dst, dst_len, fillrem );
134 }