FreeBASIC  0.91.0
dev_file_encod_open.c
Go to the documentation of this file.
1 /* UTF-encoded file devices open */
2 
3 #include "fb.h"
4 
18  NULL,
20 };
21 
22 static int hCheckBOM( FB_FILE *handle )
23 {
24  int res, bom = 0;
25  FILE *fp = (FILE *)handle->opaque;
26 
27  if( handle->mode == FB_FILE_MODE_APPEND )
28  fseek( fp, 0, SEEK_SET );
29 
30  switch( handle->encod )
31  {
32  case FB_FILE_ENCOD_UTF8:
33  if( fread( &bom, 3, 1, fp ) != 1 )
34  return 0;
35 
36  res = (bom == 0x00BFBBEF);
37  break;
38 
40  if( fread( &bom, sizeof( UTF_16 ), 1, fp ) != 1 )
41  return 0;
42 
43  /* !!!FIXME!!! only litle-endian supported */
44  res = (bom == 0x0000FEFF);
45  break;
46 
48 
49  if( fread( &bom, sizeof( UTF_32 ), 1, fp ) != 1 )
50  return 0;
51 
52  /* !!!FIXME!!! only litle-endian supported */
53  res = (bom == 0x0000FEFF);
54  break;
55 
56  default:
57  res = 0;
58  }
59 
60  if( handle->mode == FB_FILE_MODE_APPEND )
61  fseek( fp, 0, SEEK_END );
62 
63  return res;
64 }
65 
66 static int hWriteBOM( FB_FILE *handle )
67 {
68  int bom;
69  FILE *fp = (FILE *)handle->opaque;
70 
71  switch( handle->encod )
72  {
73  case FB_FILE_ENCOD_UTF8:
74  bom = 0x00BFBBEF;
75  if( fwrite( &bom, 3, 1, fp ) != 1 )
76  return 0;
77  break;
78 
80  /* !!!FIXME!!! only litle-endian supported */
81  bom = 0x0000FEFF;
82  if( fwrite( &bom, sizeof( UTF_16 ), 1, fp ) != 1 )
83  return 0;
84  break;
85 
87  /* !!!FIXME!!! only litle-endian supported */
88  bom = 0x0000FEFF;
89  if( fwrite( &bom, sizeof( UTF_32 ), 1, fp ) != 1 )
90  return 0;
91  break;
92 
93  default:
94  return 0;
95  }
96 
97  return 1;
98 }
99 
101  (
102  FB_FILE *handle,
103  const char *filename,
104  size_t fname_len
105  )
106 {
107  FILE *fp = NULL;
108  char *openmask;
109  char *fname;
110 
111  FB_LOCK();
112 
113  fname = (char*) alloca(fname_len + 1);
114  memcpy(fname, filename, fname_len);
115  fname[fname_len] = 0;
116 
117  /* Convert directory separators to whatever the current platform supports */
118  fb_hConvertPath( fname );
119 
120  handle->hooks = &hooks_dev_file;
121 
122  openmask = NULL;
123  switch( handle->mode )
124  {
125  case FB_FILE_MODE_APPEND:
126  /* will create the file if it doesn't exist */
127  openmask = "ab";
128  break;
129 
130  case FB_FILE_MODE_INPUT:
131  /* will fail if file doesn't exist */
132  openmask = "rb";
133  break;
134 
135  case FB_FILE_MODE_OUTPUT:
136  /* will create the file if it doesn't exist */
137  openmask = "wb";
138  break;
139 
140  default:
141  FB_UNLOCK();
143  }
144 
145  /* try opening */
146  if( (fp = fopen( fname, openmask )) == NULL )
147  {
148  FB_UNLOCK();
150  }
151 
152  fb_hSetFileBufSize( fp );
153 
154  handle->opaque = fp;
155 
156  if ( handle->access == FB_FILE_ACCESS_ANY)
158 
159  /* handle BOM */
160  switch( handle->mode )
161  {
162  case FB_FILE_MODE_APPEND:
163  case FB_FILE_MODE_INPUT:
164  if( !hCheckBOM( handle ) )
165  {
166  fclose( fp );
167  FB_UNLOCK();
169  }
170 
171  break;
172 
173  case FB_FILE_MODE_OUTPUT:
174  if( !hWriteBOM( handle ) )
175  {
176  fclose( fp );
177  FB_UNLOCK();
179  }
180  }
181 
182  /* calc file size */
183  handle->size = fb_DevFileGetSize( fp, handle->mode, handle->encod, TRUE );
184  if( handle->size == -1 )
185  {
186  fclose( fp );
187  FB_UNLOCK();
189  }
190 
191  FB_UNLOCK();
192 
193  return fb_ErrorSetNum( FB_RTERROR_OK );
194 }