00001 #include "slate.hpp"
00002 #ifdef WIN32
00003 static LARGE_INTEGER liZero;
00004 #endif
00005
00006 void file_module_init(struct object_heap* oh) {
00007 oh->file_index_size = SLATE_FILES_MAXIMUM;
00008 oh->file_index = (FILE**)calloc(oh->file_index_size, sizeof(FILE*));
00009 }
00010
00011 bool_t file_handle_isvalid(struct object_heap* oh, word_t file) {
00012 return (0 <= file && file < oh->file_index_size && oh->file_index[file] != NULL);
00013 }
00014
00015 word_t file_allocate(struct object_heap* oh) {
00016 word_t file;
00017 word_t initial_size = oh->file_index_size;
00018 for (file = 0; file < initial_size; ++ file) {
00019 if (!(file_handle_isvalid(oh, file)))
00020 return file;
00021 }
00022 oh->file_index_size *= 2;
00023 oh->file_index = (FILE**)realloc(oh->file_index, oh->file_index_size * sizeof(FILE*));
00024 assert(oh->file_index);
00025
00026 for (file = initial_size; file < oh->file_index_size; file++) {
00027 oh->file_index[file] = NULL;
00028 }
00029
00030 return initial_size;
00031 }
00032
00033 void file_close(struct object_heap* oh, word_t file) {
00034 if (file_handle_isvalid(oh, file)) {
00035 #ifdef WIN32
00036 CloseHandle(oh->file_index[file]);
00037 #else
00038 fclose (oh->file_index[file]);
00039 #endif
00040 oh->file_index[file] = NULL;
00041 }
00042 }
00043
00044 word_t file_open(struct object_heap* oh, struct ByteArray * name, word_t flags) {
00045 byte_t nameString[SLATE_FILE_NAME_LENGTH];
00046 word_t nameLength;
00047 #ifdef WIN32
00048 DWORD rwMode = 0;
00049 DWORD openMode = 0;
00050 #else
00051 char mode[8];
00052 word_t modeIndex = 0;
00053 #endif
00054 word_t file;
00055
00056 nameLength = extractCString(name, nameString, sizeof(nameString));
00057
00058 if (nameLength <= 0)
00059 return SLATE_ERROR_RETURN;
00060
00061 file = file_allocate(oh);
00062 if (file < 0)
00063 return SLATE_ERROR_RETURN;
00064
00065
00066 if ((flags & SF_CLEAR || flags & SF_CREATE) && (! (flags & SF_WRITE)))
00067 error("ANSI does not support clearing or creating files that are not opened for writing");
00068
00069
00070 if (flags & SF_WRITE && (! (flags & SF_READ)))
00071 error("ANSI does not support opening files for writing only");
00072
00073 if (flags & SF_WRITE) {
00074 if (flags & SF_CLEAR) {
00075 #ifdef WIN32
00076 rwMode |= GENERIC_WRITE;
00077 #else
00078 mode[modeIndex++] = 'w';
00079 #endif
00080 if (flags & SF_READ)
00081 #ifdef WIN32
00082 rwMode |= GENERIC_READ;
00083 #else
00084 mode[modeIndex++] = '+';
00085 #endif
00086 } else {
00087 #ifdef WIN32
00088 rwMode |= GENERIC_READ;
00089 #else
00090 mode[modeIndex++] = 'r';
00091 mode[modeIndex++] = '+';
00092 #endif
00093 }
00094 } else if (flags & SF_READ)
00095 #ifdef WIN32
00096 rwMode |= GENERIC_READ;
00097 #else
00098 mode[modeIndex++] = 'r';
00099 #endif
00100 else {
00101 fprintf(stderr, "Slate: Unexpected mode flags for ANSI file module: %" PRIdPTR ", falling back to \"r\"", flags);
00102 #ifdef WIN32
00103 rwMode |= GENERIC_READ;
00104 #else
00105 mode[modeIndex++] = 'r';
00106 #endif
00107 };
00108
00109 #ifdef WIN32
00110 openMode = ((flags & SF_CREATE) ? OPEN_ALWAYS : OPEN_EXISTING);
00111 #else
00112 mode[modeIndex++] = 'b';
00113 mode[modeIndex++] = 0;
00114 #endif
00115
00116 #ifdef WIN32
00117 oh->file_index[file] = CreateFile(nameString, rwMode, FILE_SHARE_READ, 0, openMode, FILE_ATTRIBUTE_NORMAL, 0);
00118 #else
00119 oh->file_index[file] = fopen((char*)nameString, mode);
00120 #endif
00121
00122 if (file_handle_isvalid(oh, file)) {
00123
00124 #ifdef WIN32
00125 if (flags & SF_CLEAR) {
00126 if (!SetFilePointerEx(oh->file_index[file], liZero, NULL, FILE_BEGIN) || !SetEndOfFile(oh->file_index[file])) {
00127 CloseHandle(oh->file_index[file]);
00128 oh->file_index[file] = 0;
00129 return SLATE_ERROR_RETURN;
00130 }
00131 }
00132 #endif
00133 return file;
00134 } else
00135 return SLATE_ERROR_RETURN;
00136 }
00137
00138 word_t file_write(struct object_heap* oh, word_t file, word_t n, char * bytes) {
00139 #ifdef WIN32
00140 DWORD bytesWritten = 0;
00141 return (WriteFile(oh->file_index[file], bytes, (DWORD)n, &bytesWritten, NULL)
00142 ? bytesWritten : SLATE_ERROR_RETURN);
00143 #else
00144 return (file_handle_isvalid(oh, file) ? fwrite (bytes, 1, n, oh->file_index[file])
00145 : SLATE_ERROR_RETURN);
00146 #endif
00147 }
00148
00149 word_t file_read(struct object_heap* oh, word_t file, word_t n, char * bytes) {
00150 #ifdef WIN32
00151 DWORD bytesRead = 0;
00152 return (file_handle_isvalid(oh, file) && ReadFile(oh->file_index[file], bytes, (DWORD)n, &bytesRead, NULL)
00153 ? bytesRead : SLATE_ERROR_RETURN);
00154 #else
00155 return (file_handle_isvalid(oh, file) ? fread (bytes, 1, n, oh->file_index[file])
00156 : SLATE_ERROR_RETURN);
00157 #endif
00158 }
00159
00160 word_t file_sizeof(struct object_heap* oh, word_t file) {
00161 #ifdef WIN32
00162 LARGE_INTEGER size;
00163 #else
00164 word_t pos, size;
00165 #endif
00166 if (!(file_handle_isvalid(oh, file)))
00167 return SLATE_ERROR_RETURN;
00168 #ifdef WIN32
00169 size.QuadPart = 0;
00170 return (GetFileSizeEx(oh->file_index[file], &size) ? size.QuadPart : SLATE_ERROR_RETURN);
00171 #else
00172 pos = ftell (oh->file_index[file]);
00173 fseek (oh->file_index[file], 0, SEEK_END);
00174 size = ftell (oh->file_index[file]);
00175 fseek (oh->file_index[file], pos, SEEK_SET);
00176 return size;
00177 #endif
00178 }
00179
00180 word_t file_seek(struct object_heap* oh, word_t file, word_t offset) {
00181 #ifdef WIN32
00182 LARGE_INTEGER pos;
00183 LARGE_INTEGER win_offset;
00184 pos.QuadPart = 0;
00185 win_offset.QuadPart = offset;
00186 return (SetFilePointerEx(oh->file_index[file], win_offset, &pos, FILE_BEGIN)
00187 ? pos.QuadPart : SLATE_ERROR_RETURN);
00188 #else
00189 return (file_handle_isvalid(oh, file) && fseek (oh->file_index[file], offset, SEEK_SET) == 0
00190 ? ftell (oh->file_index[file]) : SLATE_ERROR_RETURN);
00191 #endif
00192 }
00193
00194 word_t file_tell(struct object_heap* oh, word_t file) {
00195 #ifdef WIN32
00196 LARGE_INTEGER pos;
00197 #endif
00198 if (!file_handle_isvalid(oh, file))
00199 return SLATE_ERROR_RETURN;
00200 #ifdef WIN32
00201 pos.QuadPart = 0;
00202 return (SetFilePointerEx(oh->file_index[file], liZero, &pos, FILE_CURRENT)
00203 ? pos.QuadPart : SLATE_ERROR_RETURN);
00204 #else
00205 return ftell(oh->file_index[file]);
00206 #endif
00207 }
00208
00209 bool_t file_isatend(struct object_heap* oh, word_t file) {
00210 #ifdef WIN32
00211 LARGE_INTEGER size;
00212 LARGE_INTEGER pos;
00213 size.QuadPart = 0;
00214 pos.QuadPart = 0;
00215
00216 if (!SetFilePointerEx(oh->file_index[file], liZero, &pos, FILE_CURRENT))
00217 return SLATE_ERROR_RETURN;
00218 else
00219 return (GetFileSizeEx(oh->file_index[file], &size)
00220 ? pos.QuadPart >= size.QuadPart : SLATE_ERROR_RETURN);
00221 #else
00222 word_t c;
00223 if (!(file_handle_isvalid(oh, file)))
00224 return TRUE;
00225 c = fgetc (oh->file_index[file]);
00226 if (c == EOF)
00227 return TRUE;
00228 else {
00229 ungetc (c, oh->file_index[file]);
00230 return FALSE;
00231 }
00232 #endif
00233 }
00234
00235
00236 bool_t file_delete(struct object_heap* oh, char* filename) {
00237 #ifdef WIN32
00238 return FALSE;
00239 #else
00240 return (unlink(filename) == 0 ? TRUE : FALSE);
00241 #endif
00242 }
00243
00244 word_t slate_file_mode(mode_t mode) {
00245
00246 return mode;
00247 }
00248
00249 struct Object* file_information(struct object_heap* oh, char* filename) {
00250 #ifdef WIN32
00251 return FALSE;
00252 #else
00253 struct stat fileInfo;
00254 struct OopArray* array;
00255 if (stat(filename, &fileInfo) != 0) return oh->cached.nil;
00256 array = heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO), 5);
00257 array->elements[0] = smallint_to_object(fileInfo.st_size);
00258 array->elements[1] = smallint_to_object(fileInfo.st_atime);
00259 array->elements[2] = smallint_to_object(fileInfo.st_mtime);
00260 array->elements[3] = smallint_to_object(fileInfo.st_ctime);
00261 array->elements[4] = smallint_to_object(slate_file_mode(fileInfo.st_mode));
00262
00263 return (struct Object*)array;
00264 #endif
00265 }
00266
00267 bool_t file_rename_to(struct object_heap* oh, char* src, char* dest) {
00268 #ifdef WIN32
00269 return FALSE;
00270 #else
00271 return (rename(src, dest) == 0 ? TRUE : FALSE);
00272 #endif
00273 }