Browse Source

feat: 添加部分IO处理函数

link #7
SongZihuan 4 years ago
parent
commit
c7eb3b180e
4 changed files with 182 additions and 25 deletions
  1. 1 0
      vmcore/include/value.h
  2. 169 13
      vmcore/ofunc/src/file_.c
  3. 3 5
      vmcore/ofunc/src/vobject.c
  4. 9 7
      vmcore/src/value.c

+ 1 - 0
vmcore/include/value.h

@@ -250,6 +250,7 @@ void setResultCore(Result *ru);
 void setResult(Result *ru, Inter *inter);
 void setResultBase(Result *ru, Inter *inter);
 void setResultErrorSt(BaseErrorType type, wchar_t *error_message, bool new, FUNC);
+void setResultFromERR(enum BaseErrorType exc, FUNC_NT);
 void setResultError(BaseErrorType type, wchar_t *error_message, fline line, char *file, bool new, FUNC_NT);
 void setResultOperationNone(Result *ru, Inter *inter, LinkValue *belong);
 void setResultOperation(Result *ru, LinkValue *value);

+ 169 - 13
vmcore/ofunc/src/file_.c

@@ -39,9 +39,8 @@ ResultType file_init(O_FUNC){
     char *mode;
     setResultCore(result);
     parserArgumentUnion(ap, arg, CNEXT_NT);
-    if (!CHECK_RESULT(result)) {
+    if (!CHECK_RESULT(result))
         return result->type;
-    }
     freeResult(result);
 
     if ((file = ap[0].value)->value->type != V_file) {
@@ -71,8 +70,10 @@ ResultType file_init(O_FUNC){
     file->value->data.file.mode = mode;
     file->value->data.file.is_std = false;
     file->value->data.file.file = fopen(path, mode);
-
-    setResult(result, inter);
+    if (file->value->data.file.file == NULL)
+        setResultFromERR(E_TypeException, CNEXT_NT);
+    else
+        setResult(result, inter);
     return result->type;
 }
 
@@ -84,9 +85,8 @@ ResultType file_read(O_FUNC){
     wchar_t *tmp = NULL;
     setResultCore(result);
     parserArgumentUnion(ap, arg, CNEXT_NT);
-    if (!CHECK_RESULT(result)) {
+    if (!CHECK_RESULT(result))
         return result->type;
-    }
     freeResult(result);
 
     if ((file = ap[0].value)->value->type != V_file || file->value->data.file.file == NULL) {
@@ -94,18 +94,18 @@ ResultType file_read(O_FUNC){
         return R_error;
     }
 
-    if (ap[1].value != NULL) {
+    fseek(file->value->data.file.file, 0L, SEEK_CUR);  // 改变文件状态(什么都没做)
+    if (ap[1].value != NULL) {  // 指定数量读取
         size_t n;
         wint_t ch;
-        if (ap[1].value->value->type != V_int)
+        if (ap[1].value->value->type == V_int)
             n = ap[1].value->value->data.int_.num;
-        else if (ap[1].value->value->type != V_dou)
+        else if (ap[1].value->value->type == V_dou)
             n = (vint)ap[1].value->value->data.dou.num;
         else {
             setResultError(E_TypeException, ONLY_ACC(n, num), LINEFILE, true, CNEXT_NT);
             return R_error;
         }
-
         tmp = memWide(n);
         for (int count=0; count < n && (ch = getwc(file->value->data.file.file)) != WEOF; count++)
             tmp[count] = ch;
@@ -114,7 +114,7 @@ ResultType file_read(O_FUNC){
         size_t step = 50;
         wint_t ch;
         tmp = NULL;
-        for (int count=1; (ch = getwc(file->value->data.file.file)) != WEOF; count++) {
+        for (int count=1; (ch = fgetwc(file->value->data.file.file)) != WEOF; count++) {  // 全部读取
             if (count > n) {
                 n += step;
                 tmp = memWideExpansion(tmp, n, true);
@@ -128,6 +128,41 @@ ResultType file_read(O_FUNC){
     return result->type;
 }
 
+ResultType file_readline(O_FUNC){
+    ArgumentParser ap[] = {{.type=only_value, .must=1, .long_arg=false},
+                           {.must=-1}};
+    LinkValue *file;
+    wchar_t *tmp = NULL;
+    size_t n = 0;
+    size_t step = 50;
+    wint_t ch;
+
+    setResultCore(result);
+    parserArgumentUnion(ap, arg, CNEXT_NT);
+    if (!CHECK_RESULT(result))
+        return result->type;
+    freeResult(result);
+
+    if ((file = ap[0].value)->value->type != V_file || file->value->data.file.file == NULL) {
+        setResultError(E_TypeException, INSTANCE_ERROR(file), LINEFILE, true, CNEXT_NT);
+        return R_error;
+    }
+
+    fseek(file->value->data.file.file, 0L, SEEK_CUR);  // 改变文件状态(什么都没做)
+    tmp = NULL;
+    for (int count=1; (ch = fgetwc(file->value->data.file.file)) != WEOF && ch != '\n'; count++) {  // 读取到行末
+        if (count > n) {
+            n += step;
+            tmp = memWideExpansion(tmp, n, true);
+        }
+        tmp[count - 1] = ch;
+    }
+
+    makeStringValue(tmp, LINEFILE, CNEXT_NT);
+    memFree(tmp);
+    return result->type;
+}
+
 ResultType file_write(O_FUNC){
     ArgumentParser ap[] = {{.type=only_value, .must=1, .long_arg=false},
                            {.type=name_value, .must=1, .name=L"str", .long_arg=false},
@@ -135,9 +170,8 @@ ResultType file_write(O_FUNC){
     LinkValue *file;
     setResultCore(result);
     parserArgumentUnion(ap, arg, CNEXT_NT);
-    if (!CHECK_RESULT(result)) {
+    if (!CHECK_RESULT(result))
         return result->type;
-    }
     freeResult(result);
 
     if ((file = ap[0].value)->value->type != V_file || file->value->data.file.file == NULL) {
@@ -150,11 +184,127 @@ ResultType file_write(O_FUNC){
         return R_error;
     }
 
+    fseek(file->value->data.file.file, 0L, 1);  // 改变文件状态(什么都没做)
     fprintf(file->value->data.file.file, "%ls", ap[1].value->value->data.str.str);
     setResult(result, inter);
     return result->type;
 }
 
+ResultType file_get_seek(O_FUNC){
+    ArgumentParser ap[] = {{.type=only_value, .must=1, .long_arg=false},
+                           {.must=-1}};
+    LinkValue *file;
+    long seek;
+    setResultCore(result);
+    parserArgumentUnion(ap, arg, CNEXT_NT);
+    if (!CHECK_RESULT(result))
+        return result->type;
+    freeResult(result);
+
+    if ((file = ap[0].value)->value->type != V_file || file->value->data.file.file == NULL) {
+        setResultError(E_TypeException, INSTANCE_ERROR(file), LINEFILE, true, CNEXT_NT);
+        return R_error;
+    }
+
+    seek = ftell(file->value->data.file.file);
+    makeIntValue(seek, LINEFILE, CNEXT_NT);
+    return result->type;
+}
+
+ResultType file_err_core(O_FUNC, int type){
+    ArgumentParser ap[] = {{.type=only_value, .must=1, .long_arg=false},
+                           {.must=-1}};
+    LinkValue *file;
+    setResultCore(result);
+    parserArgumentUnion(ap, arg, CNEXT_NT);
+    if (!CHECK_RESULT(result))
+        return result->type;
+    freeResult(result);
+
+    if ((file = ap[0].value)->value->type != V_file || file->value->data.file.file == NULL) {
+        setResultError(E_TypeException, INSTANCE_ERROR(file), LINEFILE, true, CNEXT_NT);
+        return R_error;
+    }
+
+    switch (type) {
+        case 1:
+            makeBoolValue(feof(file->value->data.file.file), LINEFILE, CNEXT_NT);
+            break;
+        case 2:
+            makeBoolValue(ferror(file->value->data.file.file), LINEFILE, CNEXT_NT);
+            break;
+        case 3:
+            clearerr(file->value->data.file.file);
+        default:
+            setResult(result, inter);
+            break;
+    }
+    return result->type;
+}
+
+ResultType file_isend(O_FUNC){
+    return file_err_core(CO_FUNC(arg, var_list, result, belong), 1);
+}
+
+ResultType file_iserr(O_FUNC){
+    return file_err_core(CO_FUNC(arg, var_list, result, belong), 2);
+}
+
+ResultType file_clean_err(O_FUNC){
+    return file_err_core(CO_FUNC(arg, var_list, result, belong), 3);
+}
+
+ResultType file_seek(O_FUNC){
+    ArgumentParser ap[] = {{.type=only_value, .must=1, .long_arg=false},
+                           {.type=name_value, .must=1, .name=L"seek", .long_arg=false},
+                           {.type=name_value, .must=0, .name=L"where", .long_arg=false},
+                           {.must=-1}};
+    LinkValue *file;
+    int where;
+    setResultCore(result);
+    parserArgumentUnion(ap, arg, CNEXT_NT);
+    if (!CHECK_RESULT(result))
+        return result->type;
+    freeResult(result);
+
+    if ((file = ap[0].value)->value->type != V_file || file->value->data.file.file == NULL) {
+        setResultError(E_TypeException, INSTANCE_ERROR(file), LINEFILE, true, CNEXT_NT);
+        return R_error;
+    }
+
+    if (ap[1].value->value->type != V_int) {
+        setResultError(E_TypeException, ONLY_ACC(seek, int), LINEFILE, true, CNEXT_NT);
+        return R_error;
+    }
+
+    if (ap[2].value != NULL) {
+        if (ap[2].value->value->type != V_int) {
+            setResultError(E_TypeException, ONLY_ACC(where, int), LINEFILE, true, CNEXT_NT);
+            return R_error;
+        }
+        switch (ap[2].value->value->data.int_.num) {
+            case 0:
+                where = SEEK_SET;
+                break;
+            case 1:
+                where = SEEK_CUR;
+                break;
+            case 2:
+                where = SEEK_END;
+                break;
+            default:
+                setResultError(E_TypeException, ONLY_ACC(where, (int)0/1/2), LINEFILE, true, CNEXT_NT);
+                return R_error;
+        }
+    } else
+        where = SEEK_SET;
+
+    fgetwc(file->value->data.file.file);  // 必须先读取一个字节才可以调用seek
+    fseek(file->value->data.file.file, ap[1].value->value->data.int_.num, where);
+    setResult(result, inter);
+    return result->type;
+}
+
 ResultType file_close(O_FUNC){
     ArgumentParser ap[] = {{.type=only_value, .must=1, .long_arg=false},
                            {.must=-1}};
@@ -207,6 +357,12 @@ void registeredFile(R_FUNC){
     NameFunc tmp[] = {{L"read", file_read, object_free_},
                       {L"write", file_write, object_free_},
                       {L"close", file_close, object_free_},
+                      {L"get_seek", file_get_seek, object_free_},
+                      {L"seek", file_seek, object_free_},
+                      {L"readline", file_readline, object_free_},
+                      {L"end", file_isend, object_free_},
+                      {L"err", file_iserr, object_free_},
+                      {L"clean", file_clean_err, object_free_},
                       {inter->data.mag_func[M_ENTER], file_enter, object_free_},
                       {inter->data.mag_func[M_DEL], file_close, object_free_},
                       {inter->data.mag_func[M_EXIT], file_close, object_free_},

+ 3 - 5
vmcore/ofunc/src/vobject.c

@@ -120,11 +120,9 @@ void vobject_pow_base(LinkValue *belong, Result *result, struct Inter *inter, Va
         setResultError(E_TypeException, CUL_ERROR(Div), LINEFILE, true, CNEXT_NT);
         return;
     }
-    if (errno != 0) {
-        wchar_t *err = memStrToWcs(strerror(errno), false);
-        setResultError(E_TypeException, err, LINEFILE, true, CNEXT_NT);  // TODO-szh 设置计算错误
-        memFree(err);
-    } else
+    if (errno != 0)
+        setResultFromERR(E_TypeException, CNEXT_NT);  // TODO-szh 设置计算错误
+    else
         makeDouValue(re, LINEFILE, CNEXT_NT);
 }
 

+ 9 - 7
vmcore/src/value.c

@@ -75,10 +75,10 @@ Value *makeIntValue(vint num, fline line, char *file, FUNC_NT) {
 Value *makeDouValue(vdou num, fline line, char *file, FUNC_NT) {
     Value *tmp = NULL;
     setResultCore(result);
-//    if (isnanl(num) || isinfl(num)) {
-//        setResultError(E_TypeException, L"decimal exception / [inf/nan]", LINEFILE, true, CNEXT_NT);
-//        return NULL;
-//    }
+    if (isnanl(num) || isinfl(num)) {
+        setResultError(E_TypeException, L"decimal exception / [inf/nan]", LINEFILE, true, CNEXT_NT);
+        return NULL;
+    }
     callBackCore(inter->data.base_obj[B_DOU], NULL, line, file, 0, CNEXT_NT);
     if (!CHECK_RESULT(result))
         return NULL;
@@ -338,8 +338,10 @@ void setResultErrorSt(BaseErrorType type, wchar_t *error_message, bool new, Stat
     setResultError(type, error_message, st->line, st->code_file, new, CNEXT_NT);
 }
 
-LinkValue *findBaseError(BaseErrorType type, Inter *inter){  // TODO-szh 撤销该函数
-    return inter->data.base_exc[type];
+void setResultFromERR(enum BaseErrorType exc, FUNC_NT) {
+    wchar_t *err = memStrToWcs(strerror(errno), false);
+    setResultError(exc, err, LINEFILE, true, CNEXT_NT);
+    memFree(err);
 }
 
 static wchar_t *getErrorInfo(LinkValue *exc, int type, FUNC_NT){
@@ -416,7 +418,7 @@ void setResultError(BaseErrorType type, wchar_t *error_message, fline line, char
     if (!new && result->type != R_error)
         return;
     if (new) {
-        LinkValue *exc = findBaseError(type, inter);
+        LinkValue *exc = inter->data.base_exc[type];
         if (exc == NULL)
             exc = inter->data.base_exc[E_BaseException];
         freeResult(result);