소스 검색

feat: 可以按字节读取和写入文件

link #7
SongZihuan 4 년 전
부모
커밋
84746e7ff3
10개의 변경된 파일216개의 추가작업 그리고 11개의 파일을 삭제
  1. 2 1
      vmcore/include/inter.h
  2. 3 2
      vmcore/include/mem.h
  3. 2 0
      vmcore/include/ofunc.h
  4. 8 0
      vmcore/include/value.h
  5. 5 0
      vmcore/ofunc/include/struct_.h
  6. 67 7
      vmcore/ofunc/src/file_.c
  7. 89 0
      vmcore/ofunc/src/struct_.c
  8. 17 0
      vmcore/ofunc/src/vobject.c
  9. 2 0
      vmcore/src/ofunc.c
  10. 21 1
      vmcore/src/value.c

+ 2 - 1
vmcore/include/inter.h

@@ -7,7 +7,7 @@ struct Result;
 #define RUNGC (100)
 #define SHOULD_RUNGC(inter) ((inter)->data.start_gc && (inter)->data.run_gc >= RUNGC)
 
-#define BASEOBJSZIE (17)
+#define BASEOBJSZIE (18)
 #define VARNAMESIZE (10)
 #define BASEEXCESIZE (20)
 #define MAGFUNCSIZE (46)
@@ -29,6 +29,7 @@ struct Result;
 #define B_LISTITER (14)
 #define B_DICTITER (15)
 #define B_POINTER (16)
+#define B_STRUCT (17)
 
 #define VN_str (0)
 #define VN_num (1)

+ 3 - 2
vmcore/include/mem.h

@@ -31,7 +31,8 @@ wchar_t *memStrToWcs(char *str, bool free_old);
 #define memStrlen(p) (((p) == NULL) ? 0 : strlen((p)))
 #define memWidelen(p) (((p) == NULL) ? 0 : wcslen((p)))
 
-#define MACRO_CALLOC(var, n, size)                                             \
-  ((((var) = (typeof(var))calloc(n, size)) == NULL) ? (memError()) : (var))
+#define MACRO_CALLOC(var, n, size) ((((var) = (typeof(var))calloc(n, size)) == NULL) ? (memError()) : (var))
+
+#define MEM_CPY(to, from, size) (((to) = memCalloc(1, size)), memcpy(to, from, size))
 
 #endif // VIRTUALMATH_MEM_H

+ 2 - 0
vmcore/include/ofunc.h

@@ -19,6 +19,7 @@
 #include "file_.h"
 #include "lib_.h"
 #include "pointer.h"
+#include "struct_.h"
 
 struct Argument;
 struct VarList;
@@ -44,6 +45,7 @@ void registeredFunctionName(LinkValue *belong, Inter *inter);
 LinkValue *intCore(LinkValue *belong, LinkValue *class, Inter *inter);
 LinkValue *strCore(LinkValue *belong, LinkValue *class, Inter *inter);
 LinkValue *boolCore(LinkValue *belong, LinkValue *class, Inter *inter);
+LinkValue *structCore(LinkValue *belong, LinkValue *class, Inter *inter);
 LinkValue *douCore(LinkValue *belong, LinkValue *class, Inter *inter);
 LinkValue *passCore(LinkValue *belong, LinkValue *class, Inter *inter);
 

+ 8 - 0
vmcore/include/value.h

@@ -61,6 +61,7 @@ enum ValueType {
     V_file=11,
     V_lib=12,
     V_pointer=13,
+    V_struct=14,
 };
 
 struct Int {
@@ -75,6 +76,11 @@ struct String {
     wchar_t *str;
 };
 
+struct Struct_ {
+    int8_t *data;  // 列表
+    vint len;  // 长度
+};
+
 struct Function{
     enum {
         c_func,
@@ -168,6 +174,7 @@ struct Value{
         struct File file;
         struct Lib lib;
         struct Pointer pointer;
+        struct Struct_ struct_;
     } data;
 
     struct Value *gc_next;
@@ -254,6 +261,7 @@ LinkValue *makeLinkValue(Value *value, LinkValue *belong, enum ValueAuthority au
 void freeLinkValue(LinkValue **value);
 Value *useNoneValue(Inter *inter, Result *result);
 Value *makeBoolValue(bool bool_num, fline line, char *file, FUNC_NT);
+Value *makeStructValue(void *data, vint len, fline line, char *file, FUNC_NT);
 Value *makePassValue(fline line, char *file, FUNC_NT);
 Value *makeIntValue(vint num, fline line, char *file, FUNC_NT);
 Value *makeDouValue(vdou num, fline line, char *file, FUNC_NT);

+ 5 - 0
vmcore/ofunc/include/struct_.h

@@ -0,0 +1,5 @@
+#ifndef VIRTUALMATH_STRUCT__H
+#define VIRTUALMATH_STRUCT__H
+void registeredStruct(R_FUNC);
+void makeBaseStruct(Inter *inter);
+#endif //VIRTUALMATH_STRUCT__H

+ 67 - 7
vmcore/ofunc/src/file_.c

@@ -126,6 +126,58 @@ static ResultType file_read(O_FUNC){
     return result->type;
 }
 
+static ResultType file_read_bit(O_FUNC){
+    ArgumentParser ap[] = {{.type=only_value, .must=1, .long_arg=false},
+                           {.type=name_value, .must=0, .name=L"n", .long_arg=false},
+                           {.must=-1}};
+    LinkValue *file;
+    void *data = NULL;
+    size_t count = 0;
+    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);  // 改变文件状态(什么都没做)
+    if (ap[1].value != NULL) {  // 指定数量读取
+        vint n;
+        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)
+            n = (vint)ap[1].value->value->data.dou.num;
+        else {
+            setResultError(E_TypeException, ONLY_ACC(n, num), LINEFILE, true, CNEXT_NT);
+            return R_error;
+        }
+        data = memCalloc(n, sizeof(int8_t));  // TODO-szh in8_t 使用typedef
+        count = fread(data, sizeof(int8_t), n, file->value->data.file.file);
+    } else {
+        void *bak = NULL;
+        size_t get;
+        do {  // 全部读取
+            void *tmp = memCalloc(5, sizeof(int8_t));
+            get = fread(tmp, sizeof(int8_t), 5, file->value->data.file.file);
+            bak = data;
+            data = memCalloc(count, sizeof(int8_t));
+            memcpy(data, bak, count * sizeof(int8_t));  // 复制
+            memcpy(data + count * sizeof(int8_t), tmp, get * sizeof(int8_t));
+            memFree(bak);
+            memFree(tmp);
+            count += get;
+        } while (get == 5);
+    }
+
+    makeStructValue(data, count, LINEFILE, CNEXT_NT);
+    memFree(data);
+    return result->type;
+}
+
 static ResultType file_readline(O_FUNC){
     ArgumentParser ap[] = {{.type=only_value, .must=1, .long_arg=false},
                            {.must=-1}};
@@ -166,6 +218,7 @@ static ResultType file_write(O_FUNC){
                            {.type=name_value, .must=1, .name=L"str", .long_arg=false},
                            {.must=-1}};
     LinkValue *file;
+    vint re;
     setResultCore(result);
     parserArgumentUnion(ap, arg, CNEXT_NT);
     if (!CHECK_RESULT(result))
@@ -177,14 +230,20 @@ static ResultType file_write(O_FUNC){
         return R_error;
     }
 
-    if (ap[1].value->value->type != V_str) {
-        setResultError(E_TypeException, ONLY_ACC(str, str), LINEFILE, true, CNEXT_NT);
-        return R_error;
-    }
-
     fseek(file->value->data.file.file, 0L, 1);  // 改变文件状态(什么都没做)
-    fputws(ap[1].value->value->data.str.str, file->value->data.file.file);  // 使用fputws代替fwprintf
-    setResult(result, inter);
+    switch (ap[1].value->value->type) {
+        case V_str:
+            fputws(ap[1].value->value->data.str.str, file->value->data.file.file);  // 使用fputws代替fwprintf
+            re = memWidelen(ap[1].value->value->data.str.str);
+            break;
+        case V_struct:
+            re = (vint)fwrite(ap[1].value->value->data.struct_.data, sizeof(int8_t), ap[1].value->value->data.struct_.len, file->value->data.file.file);
+            break;
+        default:
+            setResultError(E_TypeException, ONLY_ACC(str, str), LINEFILE, true, CNEXT_NT);
+            return R_error;
+    }
+    makeIntValue(re, LINEFILE, CNEXT_NT);
     return result->type;
 }
 
@@ -412,6 +471,7 @@ void registeredFile(R_FUNC){
                       {L"clean", file_clean_err, fp_obj, .var=nfv_notpush},
                       {L"flush", file_flush, fp_obj, .var=nfv_notpush},
                       {L"getc", file_getc, fp_obj, .var=nfv_notpush},
+                      {L"readb", file_read_bit, fp_obj, .var=nfv_notpush},
                       {inter->data.mag_func[M_ENTER], file_enter, fp_obj, .var=nfv_notpush},
                       {inter->data.mag_func[M_DEL], file_close, fp_obj, .var=nfv_notpush},
                       {inter->data.mag_func[M_EXIT], file_close, fp_obj, .var=nfv_notpush},

+ 89 - 0
vmcore/ofunc/src/struct_.c

@@ -0,0 +1,89 @@
+#include "__ofunc.h"
+
+LinkValue *structCore(LinkValue *belong, LinkValue *class, Inter *inter) {
+    LinkValue *value;
+    value = make_new(inter, belong, class);
+    value->value->type = V_struct;
+    value->value->data.struct_.data = NULL;
+    value->value->data.struct_.len = 0;
+    return value;
+}
+
+static ResultType struct_new(O_FUNC){
+    LinkValue *value = NULL;
+    ArgumentParser ap[] = {{.type=only_value, .must=1, .long_arg=false},
+                           {.must=-1}};
+    int status = 1;
+    setResultCore(result);
+    arg = parserValueArgument(ap, arg, &status, NULL);
+    if (status != 1){
+        setResultError(E_ArgumentException, FEW_ARG, LINEFILE, true, CNEXT_NT);
+        return R_error;
+    }
+
+    value = make_new(inter, belong, ap[0].value);
+    value->value->type = V_struct;
+    value->value->data.struct_.data = NULL;
+    value->value->data.struct_.len = 0;
+    run_init(value, arg, LINEFILE, CNEXT_NT);
+    return result->type;
+}
+
+static ResultType struct_init(O_FUNC){
+    ArgumentParser ap[] = {{.type=only_value, .must=1, .long_arg=false},
+                           {.type=name_value, .name=L"data", .must=0, .long_arg=false},
+                           {.must=-1}};
+    LinkValue *base;
+    LinkValue *data;
+    setResultCore(result);
+    parserArgumentUnion(ap, arg, CNEXT_NT);
+    if (!CHECK_RESULT(result))
+        return result->type;
+    freeResult(result);
+
+    base = ap[0].value;
+    if ((data = ap[1].value) != NULL){
+        memFree(base->value->data.struct_.data);
+        base->value->data.struct_.len = 0;
+        switch (data->value->type) {
+            case V_int:
+                MEM_CPY(base->value->data.struct_.data, &(data->value->data.int_.num), sizeof(vint));
+                base->value->data.struct_.len = sizeof(vint) / sizeof(int8_t);
+                break;
+            case V_dou:
+                MEM_CPY(base->value->data.struct_.data, &(data->value->data.dou.num), sizeof(vdou));
+                base->value->data.struct_.len = sizeof(vdou) / sizeof(int8_t);
+                break;
+            case V_struct:
+                MEM_CPY(base->value->data.struct_.data, &data->value->data.struct_.data, data->value->data.struct_.len * sizeof(int8_t));
+                base->value->data.struct_.len = data->value->data.struct_.len;
+                break;
+            case V_str:
+                MEM_CPY(base->value->data.struct_.data, &data->value->data.str.str, memWidelen(data->value->data.str.str) * sizeof(wchar_t));
+                base->value->data.struct_.len = (sizeof(wchar_t) * memWidelen(data->value->data.str.str)) / sizeof(int8_t);
+                break;
+            default:
+                setResultError(E_ArgumentException, ONLY_ACC(data, int/str/struct), LINEFILE, true, CNEXT_NT);
+                break;
+        }
+    }
+    setResult(result, inter);
+    return result->type;
+}
+
+void registeredStruct(R_FUNC){
+    LinkValue *object = inter->data.base_obj[B_BOOL];
+    NameFunc tmp[] = {{inter->data.mag_func[M_NEW], struct_new, fp_class, .var=nfv_notpush},
+                      {inter->data.mag_func[M_INIT], struct_init, fp_obj, .var=nfv_notpush},
+                      {NULL, NULL}};
+    gc_addTmpLink(&object->gc_status);
+    addBaseClassVar(L"struct", object, belong, inter);
+    iterBaseClassFunc(tmp, object, CFUNC_CORE(inter->var_list));
+    gc_freeTmpLink(&object->gc_status);
+}
+
+void makeBaseStruct(Inter *inter){
+    LinkValue *bool_ = makeBaseChildClass(inter->data.base_obj[B_VOBJECT], inter);
+    gc_addStatementLink(&bool_->gc_status);
+    inter->data.base_obj[B_STRUCT] = bool_;
+}

+ 17 - 0
vmcore/ofunc/src/vobject.c

@@ -411,6 +411,9 @@ static ResultType vobject_bool(O_FUNC) {
         case V_file:
             result_ = value->data.file.file != NULL;
             break;
+        case V_struct:
+            result_ = value->data.struct_.len > 0;
+            break;
         default:
             setResultError(E_TypeException, CUL_ERROR(bool), LINEFILE, true, CNEXT_NT);
             return R_error;
@@ -456,6 +459,20 @@ static ResultType vobject_repo(O_FUNC) {
         case V_str:
             repo = memWidecpy(value->data.str.str);
             break;
+        case V_struct:
+            if (value->data.struct_.data != NULL ){
+                char *tmp = memStrcpy("(");
+                for (vint i = 0; i < value->data.struct_.len; i ++) {
+                    char val[20];
+                    snprintf(val, 20, "%x ", value->data.struct_.data[i]);
+                    tmp = memStrcat(tmp, val, true, false);
+                }
+                tmp[memStrlen(tmp) - 1] = ')';  // 去掉一个空格, 改成括号
+                repo = memStrToWcs(tmp, true);
+                break;
+            } else
+                repo = memWidecpy(L"(struct NULL)");
+            break;
         case V_func: {
             char str[30] = {NUL};
             snprintf(str, 30, "(func on %p)", value);

+ 2 - 0
vmcore/src/ofunc.c

@@ -15,6 +15,7 @@ static Registered base_func_list[] = {registeredVObject,
                                       registeredFile,
                                       registeredLib,
                                       registeredPointer,
+                                      registeredStruct,
 
                                       registeredSysFunction,
                                       registeredIOFunction,
@@ -68,6 +69,7 @@ void registeredFunctionName(LinkValue *belong, Inter *inter) {
     makeBaseFile(inter);
     makeBaseLib(inter);
     makeBasePointer(inter);
+    makeBaseStruct(inter);
 
     makeBaseStr(inter);
     functionPresetting(inter->data.base_obj[B_FUNCTION], inter);  // 预设定function的__new__方法

+ 21 - 1
vmcore/src/value.c

@@ -48,6 +48,23 @@ Value *makeBoolValue(bool bool_num, fline line, char *file, FUNC_NT) {
     return tmp;
 }
 
+Value *makeStructValue(void *data, vint len, fline line, char *file, FUNC_NT) {
+    Value *tmp = NULL;
+    setResultCore(result);
+    if (inter->data.free_mode) {
+        callBackCore(inter->data.base_obj[B_STRUCT], NULL, line, file, 0, CNEXT_NT);
+        if (!CHECK_RESULT(result))
+            return NULL;
+    } else
+        setResultOperation(result, structCore(belong, inter->data.base_obj[B_STRUCT], inter));
+    tmp = result->value->value;
+    if (data != NULL) {
+        tmp->data.struct_.data = MEM_CPY(tmp->data.struct_.data, data, len * sizeof(int8_t));
+        tmp->data.struct_.len = len;
+    }
+    return tmp;
+}
+
 Value *makePassValue(fline line, char *file, FUNC_NT){
     Value *tmp = NULL;
     setResultCore(result);
@@ -252,6 +269,9 @@ void freeValue(Value **value) {
         case V_str:
             memFree(free_value->data.str.str);
             break;
+        case V_struct:
+            memFree(free_value->data.struct_.data);
+            break;
         case V_file:
             memFree(free_value->data.file.mode);
             memFree(free_value->data.file.path);
@@ -277,7 +297,7 @@ void freeValue(Value **value) {
     return_: return;
 }
 
-LinkValue *makeLinkValue(Value *value, LinkValue *belong, enum ValueAuthority aut, Inter *inter) {  // TODO-szh 为LinkValue添加gc_tmpLink
+LinkValue *makeLinkValue(Value *value, LinkValue *belong, enum ValueAuthority aut, Inter *inter) {
     LinkValue *tmp;
     MACRO_CALLOC(tmp, 1, sizeof(LinkValue));
     tmp->belong = belong;