static ekU32 fileLines(struct ekContext *E, ekU32 argCount) { ekValue *thisValue; ekValue *ret = ekValueNullPtr; ekValue *lineValue; ekValue *chompValue = NULL; ekBool chomp = ekFalse; ekFile *file; if(!ekContextGetArgs(E, argCount, "*F|?", &thisValue, &chompValue)) { return ekContextArgsFailure(E, argCount, "file.lines([optional bool] chompNewline)"); } file = (ekFile *)thisValue->ptrVal; if(chompValue) { chompValue = ekValueToBool(E, chompValue); chomp = chompValue->boolVal; ekValueRemoveRefNote(E, chompValue, "chompValue temporary no longer needed"); } switchState(E, file, EFS_READ); ret = ekValueCreateArray(E); while((lineValue = readLineInternal(E, file, chomp)) != ekValueNullPtr) { ekValueArrayPush(E, ret, lineValue); } ekValueRemoveRefNote(E, thisValue, "lines no longer needs thisValue"); ekContextReturn(E, ret); // will be the data if we succesfully read }
static ekU32 fileRead(struct ekContext *E, ekU32 argCount) { ekValue *thisValue; ekValue *ret = ekValueNullPtr; ekValue *bytesValue = NULL; int bytes = 0; ekFile *file; if(!ekContextGetArgs(E, argCount, "*F|i", &thisValue, &bytesValue)) { return ekContextArgsFailure(E, argCount, "file.read([optional int] bytes)"); } file = (ekFile *)thisValue->ptrVal; switchState(E, file, EFS_READ); if(file->handle) { if(bytesValue) { bytesValue = ekValueToInt(E, bytesValue); bytes = bytesValue->intVal; ekValueRemoveRefNote(E, bytesValue, "bytesValue temporary no longer needed"); } else { // we want "the rest" of the file (could be the whole thing if you just opened it) int end; int currentPos = ftell(file->handle); fseek(file->handle, 0, SEEK_END); end = ftell(file->handle); fseek(file->handle, currentPos, SEEK_SET); bytes = end - currentPos; } if(bytes > 0) { char *data = ekAlloc(bytes+1); int bytesRead = fread(data, 1, bytes, file->handle); if(bytesRead >= 0) { data[bytesRead] = 0; ret = ekValueDonateString(E, data); } else { ekFree(data); } } } ekValueRemoveRefNote(E, thisValue, "fileRead no longer needs thisValue"); ekContextReturn(E, ret); // will be the data if we succesfully read }
static struct ekValue *fileFuncToString(struct ekContext *E, struct ekValue *p) { ekFile *file = (ekFile *)p->ptrVal; ekValueAddRefNote(E, file->filename, "fileFuncToString adding filename ref"); ekValueRemoveRefNote(E, p, "fileFuncToString doesnt need file anymore"); return file->filename; }
static ekU32 fileMemberSize(struct ekContext *E, ekU32 argCount) { ekValue *thisValue; ekValue *ret = ekValueNullPtr; ekFile *file; if(!ekContextGetArgs(E, argCount, "*F", &thisValue)) { return ekContextArgsFailure(E, argCount, "file.size()"); } file = (ekFile *)thisValue->ptrVal; if(file->handle) { int end; int currentPos = ftell(file->handle); fseek(file->handle, 0, SEEK_END); end = ftell(file->handle); fseek(file->handle, currentPos, SEEK_SET); ret = ekValueCreateInt(E, end); } ekValueRemoveRefNote(E, thisValue, "fileMemberSize doesnt need this anymore"); ekContextReturn(E, ret); }
static ekU32 fileSize(struct ekContext *E, ekU32 argCount) { ekValue *ret = ekValueNullPtr; ekValue *filenameValue; ekFile *file; struct stat s; if(!ekContextGetArgs(E, argCount, "s", &filenameValue)) { return ekContextArgsFailure(E, argCount, "file.size(path)"); } if(stat(ekValueSafeStr(file->filename), &s) != -1) { if(S_ISDIR(s.st_mode)) { return ekContextArgsFailure(E, 0, "file.size() does not work on directories"); } else { ret = ekValueCreateInt(E, s.st_size); } } ekValueRemoveRefNote(E, filenameValue, "fileSize doesnt need filename anymore"); ekContextReturn(E, ret); }
static ekU32 fileWrite(struct ekContext *E, ekU32 argCount) { ekValue *thisValue; ekValue *ret = ekValueNullPtr; ekValue *dataValue = NULL; ekFile *file; if(!ekContextGetArgs(E, argCount, "*Fs", &thisValue, &dataValue)) { return ekContextArgsFailure(E, argCount, "file.write([string] data)"); } file = (ekFile *)thisValue->ptrVal; if((file->state != EFS_WRITE) && (file->state != EFS_APPEND)) { switchState(E, file, EFS_WRITE); } if(file->handle) { const char *data = ekValueSafeStr(dataValue); int len = strlen(data); int bytesWritten = fwrite(data, 1, len, file->handle); if(bytesWritten == len) { ret = ekValueCreateInt(E, 1); } } ekValueRemoveRefNote(E, thisValue, "fileWrite no longer needs thisValue"); ekContextReturn(E, ret); // will be true if we successfully wrote }
static ekU32 fileLs(struct ekContext *E, ekU32 argCount) { ekValue *filenameValue = NULL; ekValue *arrayValue = NULL; if(!ekContextGetArgs(E, argCount, "s", &filenameValue)) { return ekContextArgsFailure(E, argCount, "file.ls(dirpath)"); } arrayValue = ekValueCreateArray(E); #ifdef USE_DIRENT { DIR *dir = opendir(ekValueSafeStr(filenameValue)); if(dir) { struct dirent *entry; while((entry = readdir(dir)) != NULL) { if(strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) { ekValueArrayPush(E, arrayValue, ekValueCreateString(E, entry->d_name)); } } closedir(dir); } } #endif ekValueRemoveRefNote(E, filenameValue, "fileExists doesnt need filename anymore"); ekContextReturn(E, arrayValue); }
static ekValue *absolutePath(struct ekContext *E, ekValue *path) { char temppath[MAX_PATH_LENGTH]; realpath(ekValueSafeStr(path), temppath); ekValueRemoveRefNote(E, path, "absolutePath doesn't need relative path anymore"); return ekValueCreateString(E, temppath); }
static void ekRegexDestroy(ekContext *E, ekRegex *regex) { ekValueRemoveRefNote(E, regex->subject, "ekRegex no longer needs subject"); if(regex->regex) { pcre_free(regex->regex); } ekFree(regex); }
static void fileFuncClear(struct ekContext *E, struct ekValue *p) { ekFile *file = (ekFile *)p->ptrVal; if(!file->permanent) { switchState(E, file, EFS_CLOSED); } ekValueRemoveRefNote(E, file->filename, "file doesnt need filename anymore"); ekFree(file); }
static ekU32 fileIsDir(struct ekContext *E, ekU32 argCount) { ekValue *filenameValue; int isdir = 0; if(!ekContextGetArgs(E, argCount, "s", &filenameValue)) { return ekContextArgsFailure(E, argCount, "file.isdir(path)"); } isdir = isDir(E, filenameValue); ekValueRemoveRefNote(E, filenameValue, "fileExists doesnt need filename anymore"); ekContextReturnInt(E, isdir); }
static ekU32 regexMatch(struct ekContext *E, ekU32 argCount) { ekValue *results = ekValueNullPtr; ekRegex *regex = regexCreateMatchFromArgs(E, argCount, "re.match([string] subject, [string] pattern, [optional string] options)"); if(regex) { results = ekValueCreateArray(E); if(!ekRegexMatchNext(E, regex, results)) { ekValueRemoveRefNote(E, results, "regex match failed, throwing out results"); results = ekValueNullPtr; } ekRegexDestroy(E, regex); } ekContextReturn(E, results); }
static ekU32 fileOpenInternal(struct ekContext *E, ekValue *fileValue, ekValue *modesValue) { ekValue *ret = ekValueNullPtr; ekFile *file = (ekFile *)fileValue->ptrVal; if(isDir(E, file->filename)) { return ekContextArgsFailure(E, 0, "file.open() does not work on directories"); } { const char *c; const char *modes = "r"; int state = EFS_READ; if(modesValue) { modes = ekValueSafeStr(modesValue); } for(c = modes; *c; ++c) { switch(*c) { case 'r': state = EFS_READ; break; case 'w': state = EFS_WRITE; break; case 'a': state = EFS_APPEND; break; }; } switchState(E, file, state); if(file->handle) { ret = fileValue; } else { ekValueRemoveRefNote(E, fileValue, "fileOpen failed, so forget about fileValue"); } } ekContextReturn(E, ret); }
static ekU32 fileExists(struct ekContext *E, ekU32 argCount) { ekValue *filenameValue = NULL; struct stat s; int exists = 0; if(!ekContextGetArgs(E, argCount, "s", &filenameValue)) { return ekContextArgsFailure(E, argCount, "file.exists(path)"); } if(stat(ekValueSafeStr(filenameValue), &s) != -1) { exists = 1; } ekValueRemoveRefNote(E, filenameValue, "fileExists doesnt need filename anymore"); ekContextReturnInt(E, exists); }
static ekU32 fileClose(struct ekContext *E, ekU32 argCount) { ekValue *thisValue; ekValue *ret = ekValueNullPtr; ekValue *filenameValue; ekFile *file; if(!ekContextGetArgs(E, argCount, "*F", &thisValue)) { return ekContextArgsFailure(E, argCount, "file.close()"); } file = (ekFile *)thisValue->ptrVal; if(switchState(E, file, EFS_CLOSED)) { ret = ekValueCreateInt(E, 1); } ekValueRemoveRefNote(E, thisValue, "fileClose doesnt need this anymore"); ekContextReturn(E, ret); }
static ekU32 regexGMatchIterator(struct ekContext *E, ekU32 argCount) { ekFrame *frame = ekArrayTop(E, &E->frames); ekValue *regexValue; ekRegex *regex; ekValue *results; ekAssert(frame->closure && frame->closure->closureVars); regexValue = ekMapGetS2P(E, frame->closure->closureVars, "regex"); regex = (ekRegex *)regexValue->ptrVal; ekAssert(argCount == 0); ekContextPopValues(E, argCount); results = ekValueCreateArray(E); if(!ekRegexMatchNext(E, regex, results)) { ekValueRemoveRefNote(E, results, "regex gmatch failed, throwing out results"); results = ekValueNullPtr; } ekContextReturn(E, results); }