-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathdev_file_open.bas
178 lines (147 loc) · 4.44 KB
/
dev_file_open.bas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/' file device '/
#include "fb.bi"
dim shared as FB_FILE_HOOKS hooks_dev_file = ( _
@fb_DevFileEof, _
@fb_DevFileClose, _
@fb_DevFileSeek, _
@fb_DevFileTell, _
@fb_DevFileRead, _
@fb_DevFileReadWstr, _
@fb_DevFileWrite, _
@fb_DevFileWriteWstr, _
@fb_DevFileLock, _
@fb_DevFileUnlock, _
@fb_DevFileReadLine, _
@fb_DevFileReadLineWstr, _
NULL, _
@fb_DevFileFlush _
)
extern "C"
sub fb_hSetFileBufSize( fp as FILE ptr )
/' change the default buffer size '/
setvbuf( fp, NULL, _IOFBF, FB_FILE_BUFSIZE )
/' Note: setvbuf() is only allowed to be called before doing any I/O
with that FILE handle '/
end sub
function fb_DevFileOpen( handle as FB_FILE ptr, filename as const ubyte ptr, fname_len as size_t ) as long
dim as FILE ptr fp = NULL
dim as ubyte ptr openmask = NULL
dim as ubyte ptr fname
dim as long errorRet = FB_RTERROR_OK
FB_LOCK()
fname = strdup( filename )
/' Convert directory separators to whatever the current platform supports '/
fb_hConvertPath( fname )
handle->hooks = @hooks_dev_file
select case ( handle->mode )
case FB_FILE_MODE_APPEND:
/' will create the file if it doesn't exist '/
openmask = sadd("ab")
case FB_FILE_MODE_INPUT:
/' will fail if file doesn't exist '/
openmask = sadd("rt")
case FB_FILE_MODE_OUTPUT:
/' will create the file if it doesn't exist '/
openmask = sadd("wb")
case FB_FILE_MODE_BINARY, FB_FILE_MODE_RANDOM:
select case ( handle->access )
case FB_FILE_ACCESS_WRITE:
openmask = sadd("wb")
case FB_FILE_ACCESS_READ:
openmask = sadd("rb")
case else:
/' w+ would erase the contents '/
openmask = sadd("r+b")
end select
end select
if ( openmask = NULL ) then
errorRet = FB_RTERROR_ILLEGALFUNCTIONCALL
goto unlockExit
end if
handle->size = -1
select case (handle->mode)
case FB_FILE_MODE_BINARY, FB_FILE_MODE_RANDOM:
/' try opening '/
fp = fopen( fname, openmask )
if ( fp = NULL ) then
/' if file was not found and in READ/WRITE (or ANY) mode,
* create it '/
if ( handle->access = FB_FILE_ACCESS_ANY or handle->access = FB_FILE_ACCESS_READWRITE ) then
fp = fopen( fname, "w+b" )
/' if file could not be created and in ANY mode, try opening as read-only '/
if ( (fp = NULL) andalso (handle->access=FB_FILE_ACCESS_ANY) ) then
fp = fopen( fname, "rb" )
if (fp <> NULL) then
' don't forget to set the effective access mode ...
handle->access = FB_FILE_ACCESS_READ
end if
end if
end if
if ( fp = NULL ) then
errorRet = FB_RTERROR_FILENOTFOUND
goto unlockExit
end if
end if
fb_hSetFileBufSize( fp )
/' special case, fseek() is unreliable in text-mode, so the file size
must be calculated in binary mode - bin mode can't be used for text
input because newlines must be converted, and EOF char (27) handled '/
case FB_FILE_MODE_INPUT:
/' try opening in binary mode '/
fp = fopen( fname, "rb" )
if( fp = NULL ) then
errorRet = FB_RTERROR_FILENOTFOUND
goto unlockExit
end if
fb_hSetFileBufSize( fp )
/' calc file size '/
handle->size = fb_DevFileGetSize( fp, FB_FILE_MODE_INPUT, handle->encod, FALSE )
if ( handle->size = -1 ) then
errorRet = FB_RTERROR_ILLEGALFUNCTIONCALL
goto fileCloseExit
end if
/' now reopen it in text-mode '/
fp = freopen( fname, openmask, fp )
if ( fp = NULL ) then
errorRet = FB_RTERROR_FILENOTFOUND
goto unlockExit
end if
fb_hSetFileBufSize( fp )
/' skip BOM, if any '/
fb_hDevFileSeekStart( fp, FB_FILE_MODE_INPUT, handle->encod, FALSE )
case else:
/' try opening '/
fp = fopen( fname, openmask )
if ( fp = NULL ) then
errorRet = FB_RTERROR_FILENOTFOUND
goto unlockExit
end if
fb_hSetFileBufSize( fp )
end select
if ( handle->size = -1 ) then
/' calc file size '/
handle->size = fb_DevFileGetSize( fp, handle->mode, handle->encod, TRUE )
if ( handle->size = -1 ) then
errorRet = FB_RTERROR_ILLEGALFUNCTIONCALL
goto fileCloseExit
end if
end if
handle->opaque = fp
if (handle->access = FB_FILE_ACCESS_ANY) then
handle->access = FB_FILE_ACCESS_READWRITE
end if
/' We just need this for TAB(n) and SPC(n) '/
if ( strcasecmp( fname, "CON" ) = 0 ) then
handle->type = FB_FILE_TYPE_CONSOLE
end if
fileCloseExit:
/' close the file if there was any error '/
if( errorRet <> FB_RTERROR_OK ) then
fclose( fp )
end if
unlockExit:
FB_UNLOCK()
free( fname )
return fb_ErrorSetNum( errorRet )
end function
end extern