~jason2605/dictu/trunk

« back to all changes in this revision

Viewing changes to c/optionals/path.c

  • Committer: GitHub
  • Author(s): Jason_000
  • Date: 2020-10-20 16:51:18 UTC
  • mfrom: (30.1.224)
  • Revision ID: git-v1:fa606671b5c967823ba21ca770618f5e33377817
Tags: v0.11.0
Merge pull request #291 from dictu-lang/develop

Release 0.11.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#include "path.h"
2
2
 
 
3
#if defined(_WIN32) && !defined(S_ISDIR)
 
4
#define S_ISDIR(M) (((M) & _S_IFDIR) == _S_IFDIR)
 
5
#endif
 
6
 
3
7
#ifdef HAS_REALPATH
4
8
static Value realpathNative(VM *vm, int argCount, Value *args) {
5
9
    if (argCount != 1) {
56
60
 
57
61
    int len = PathString->length;
58
62
 
59
 
    if (!len || (len == 1 && *path != DIR_SEPARATOR)) {
 
63
    if (!len || (len == 1 && !IS_DIR_SEPARATOR(*path))) {
60
64
        return OBJ_VAL(copyString(vm, "", 0));
61
65
    }
62
66
 
63
67
    char *p = path + len - 1;
64
 
    while (p > path && (*(p - 1) != DIR_SEPARATOR)) --p;
 
68
    while (p > path && !IS_DIR_SEPARATOR(*(p - 1))) --p;
65
69
 
66
70
    return OBJ_VAL(copyString(vm, p, (len - (p - path))));
67
71
}
141
145
        sep--;
142
146
    }
143
147
 
144
 
    if (sep == path && *sep != DIR_SEPARATOR) {
 
148
    if (sep == path && !IS_DIR_SEPARATOR(*sep)) {
145
149
        return OBJ_VAL(copyString(vm, ".", 1));
146
150
    }
147
151
 
168
172
    return BOOL_VAL(stat(path, &buffer) == 0);
169
173
}
170
174
 
 
175
static Value isdirNative(VM *vm, int argCount, Value *args) {
 
176
    if (argCount != 1) {
 
177
        runtimeError(vm, "isdir() takes 1 argument (%d given)", argCount);
 
178
        return EMPTY_VAL;
 
179
    }
 
180
 
 
181
    if (!IS_STRING(args[0])) {
 
182
        runtimeError(vm, "isdir() argument must be a string");
 
183
        return EMPTY_VAL;
 
184
    }
 
185
 
 
186
    char *path = AS_CSTRING(args[0]);
 
187
    struct stat path_stat;
 
188
    stat(path, &path_stat);
 
189
 
 
190
    if (S_ISDIR(path_stat.st_mode))
 
191
        return TRUE_VAL;
 
192
 
 
193
    return FALSE_VAL;
 
194
 
 
195
}
 
196
 
 
197
static Value listdirNative(VM *vm, int argCount, Value *args) {
 
198
    if (argCount > 1) {
 
199
        runtimeError(vm, "listdir() takes 0 or 1 arguments (%d given)", argCount);
 
200
        return EMPTY_VAL;
 
201
    }
 
202
 
 
203
    char *path;
 
204
    if (argCount == 0) {
 
205
        path = ".";
 
206
    } else {
 
207
        if (!IS_STRING(args[0])) {
 
208
            runtimeError(vm, "listdir() argument must be a string");
 
209
            return EMPTY_VAL;
 
210
        }
 
211
        path = AS_CSTRING(args[0]);
 
212
    }
 
213
 
 
214
    ObjList *dir_contents = initList(vm);
 
215
    push(vm, OBJ_VAL(dir_contents));
 
216
 
 
217
    #ifdef _WIN32
 
218
    char *searchPath = malloc(strlen(path) + 4);
 
219
    if (searchPath == NULL) {
 
220
        runtimeError(vm, "Memory error on listdir()!");
 
221
        return EMPTY_VAL;
 
222
    }
 
223
    strcpy(searchPath, path);
 
224
    strcat(searchPath, "\\*");
 
225
 
 
226
    WIN32_FIND_DATAA file;
 
227
    HANDLE dir = FindFirstFile(searchPath, &file);
 
228
    if (dir == INVALID_HANDLE_VALUE) {
 
229
        runtimeError(vm, "%s is not a path!", path);
 
230
        free(searchPath);
 
231
        return EMPTY_VAL;
 
232
    }
 
233
 
 
234
    do {
 
235
        if (strcmp(file.cFileName, ".") == 0 || strcmp(file.cFileName, "..") == 0) {
 
236
            continue;
 
237
        }
 
238
 
 
239
        Value fileName = OBJ_VAL(copyString(vm, file.cFileName, strlen(file.cFileName)));
 
240
        push(vm, fileName);
 
241
        writeValueArray(vm, &dir_contents->values, fileName);
 
242
        pop(vm);
 
243
    } while (FindNextFile(dir, &file) != 0);
 
244
 
 
245
    FindClose(dir);
 
246
    free(searchPath);
 
247
    #else
 
248
    struct dirent *dir;
 
249
    DIR *d;
 
250
    d = opendir(path);
 
251
    if (d) {
 
252
        while ((dir = readdir(d)) != NULL) {
 
253
            char *inode_name = dir->d_name;
 
254
            if (strcmp(inode_name, ".") == 0 || strcmp(inode_name, "..") == 0)
 
255
                continue;
 
256
            Value inode_value = OBJ_VAL(copyString(vm, inode_name, strlen(inode_name)));
 
257
            push(vm, inode_value);
 
258
            writeValueArray(vm, &dir_contents->values, inode_value);
 
259
            pop(vm);
 
260
        }
 
261
    } else {
 
262
        runtimeError(vm, "%s is not a path!", path);
 
263
        return EMPTY_VAL;
 
264
    }
 
265
    #endif
 
266
 
 
267
    pop(vm);
 
268
 
 
269
    return OBJ_VAL(dir_contents);
 
270
}
 
271
 
171
272
ObjModule *createPathClass(VM *vm) {
172
273
    ObjString *name = copyString(vm, "Path", 4);
173
274
    push(vm, OBJ_VAL(name));
180
281
#ifdef HAS_REALPATH
181
282
    defineNative(vm, &module->values, "realpath", realpathNative);
182
283
    defineNativeProperty(vm, &module->values, "errno", NUMBER_VAL(0));
183
 
    defineNative(vm, &module->values, "strerror", strerrorNative); // only realpath uset errno
 
284
    defineNative(vm, &module->values, "strerror", strerrorNative); // only realpath uses errno
184
285
#endif
185
286
    defineNative(vm, &module->values, "isAbsolute", isAbsoluteNative);
186
287
    defineNative(vm, &module->values, "basename", basenameNative);
187
288
    defineNative(vm, &module->values, "extname", extnameNative);
188
289
    defineNative(vm, &module->values, "dirname", dirnameNative);
189
290
    defineNative(vm, &module->values, "exists", existsNative);
 
291
    defineNative(vm, &module->values, "isdir", isdirNative);
 
292
    defineNative(vm, &module->values, "listdir", listdirNative);
190
293
 
191
294
    defineNativeProperty(vm, &module->values, "delimiter", OBJ_VAL(
192
295
        copyString(vm, PATH_DELIMITER_AS_STRING, PATH_DELIMITER_STRLEN)));