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 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 fileIterate(struct ekContext *E, ekU32 argCount) { ekValue *thisValue; ekValue *ret = ekValueNullPtr; ekValue *chompValue = NULL; ekFile *file; ekValue *closure; if(!ekContextGetArgs(E, argCount, "*F|?", &thisValue, &chompValue)) { return ekContextArgsFailure(E, argCount, "file.iterate([optional bool] chompNewline)"); } file = (ekFile *)thisValue->ptrVal; if(chompValue) { chompValue = ekValueToBool(E, chompValue); } else { chompValue = ekValueCreateInt(E, 0); } closure = ekValueCreateCFunction(E, fileIterator); closure->closureVars = ekMapCreate(E, EMKT_STRING); ekMapGetS2P(E, closure->closureVars, "file") = thisValue; ekMapGetS2P(E, closure->closureVars, "chomp") = chompValue; ekContextReturn(E, closure); }
static ekU32 regexSubInternal(struct ekContext * E, ekU32 argCount, ekBool forceGlobal) { ekValue * subject = NULL; ekValue * pattern = NULL; ekValue * replace = NULL; ekValue * options = NULL; ekValue * result = ekValueNullPtr; ekRegex * regex; int count = 0; if (!ekContextGetArgs(E, argCount, "sss|s", &subject, &pattern, &replace, &options)) { return ekContextArgsFailure(E, argCount, "re.sub([string] subject, [string] pattern, [string] replacement, [optional string] options)"); } result = ekValueCreateString(E, ""); regex = ekRegexCreate(E, subject, pattern, options); if (forceGlobal) { regex->global = ekTrue; } if (regex) { count = ekRegexSub(E, regex, replace, &result->stringVal); ekRegexDestroy(E, regex); } ekContextReturn(E, result); }
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 fileMemberOpen(struct ekContext *E, ekU32 argCount) { ekValue *thisValue; ekValue *modesValue = NULL; if(!ekContextGetArgs(E, argCount, "*F|s", &thisValue, &modesValue)) // assumes "r" if absent { return ekContextArgsFailure(E, argCount, "fileVal.open([string] modes)"); } return fileOpenInternal(E, thisValue, modesValue); }
static ekU32 ekiInt(struct ekContext * E, ekU32 argCount) { ekValue * v = NULL; if (!ekContextGetArgs(E, argCount, "?", &v)) { return ekContextArgsFailure(E, argCount, "int(value)"); } ekArrayPush(E, &E->stack, ekValueToInt(E, v)); return 1; }
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 ekRegex * regexCreateMatchFromArgs(struct ekContext * E, ekU32 argCount, const char * errorString) { ekValue * pattern = NULL; ekValue * subject = NULL; ekValue * options = NULL; ekRegex * regex; if (!ekContextGetArgs(E, argCount, "ss|s", &subject, &pattern, &options)) { ekContextArgsFailure(E, argCount, errorString); return NULL; } return ekRegexCreate(E, subject, pattern, options); }
static ekU32 fileAbs(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)"); } filenameValue = absolutePath(E, filenameValue); ekContextReturn(E, filenameValue); }
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 fileCreateIterator(struct ekContext *E, ekU32 argCount) { ekValue *thisValue = NULL; ekValue *closure; if(!ekContextGetArgs(E, argCount, "F", &thisValue)) { return ekContextArgsFailure(E, argCount, "file iterator missing argument"); } closure = ekValueCreateCFunction(E, fileIterator); closure->closureVars = ekMapCreate(E, EMKT_STRING); ekMapGetS2P(E, closure->closureVars, "file") = thisValue; ekMapGetS2P(E, closure->closureVars, "chomp") = ekValueCreateInt(E, 0); ekContextReturn(E, closure); }
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 newFile(struct ekContext *E, ekU32 argCount) { ekValue *ret = ekValueNullPtr; ekValue *filenameValue = NULL; ekFile *file; if(!ekContextGetArgs(E, argCount, "s", &filenameValue)) { return ekContextArgsFailure(E, argCount, "file([string] filename)"); } ret = ekValueCreate(E, ekValueTypeId(E, 'F')); file = (ekFile *)ekAlloc(sizeof(ekFile)); file->filename = absolutePath(E, filenameValue); // takes ownership ret->ptrVal = file; 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 fileOpen(struct ekContext *E, ekU32 argCount) { ekValue *fileValue = ekValueNullPtr; ekValue *filenameValue; ekValue *modesValue = NULL; ekFile *file; if(!ekContextGetArgs(E, argCount, "s|s", &filenameValue, &modesValue)) // assumes "r" if absent { return ekContextArgsFailure(E, argCount, "file.open([string] filename, [string] modes)"); } fileValue = ekValueCreate(E, ekValueTypeId(E, 'F')); file = (ekFile *)ekAlloc(sizeof(ekFile)); file->filename = absolutePath(E, filenameValue); // takes ownership fileValue->ptrVal = file; return fileOpenInternal(E, fileValue, modesValue); }
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); }