Selaa lähdekoodia

optimize hashlib package

dreamcmi 3 vuotta sitten
vanhempi
sitoutus
a91c3698ab

+ 1 - 7
package/hashlib/_hashlib.pyi

@@ -1,11 +1,5 @@
 class Hash:
-    def new(self, mode: str): ...
-    def md5(self, data: any): ...
-    def sha1(self, data: any): ...
-    def sha224(self, data: any): ...
-    def sha256(self, data: any): ...
-    def sha384(self, data: any): ...
-    def sha512(self, data: any): ...
+    def new(self, mode: str, data:any): ...
     def update(self, data: any): ...
     def digest(self) -> any: ...
     def hexdigest(self) -> str: ...

+ 95 - 173
package/hashlib/_hashlib_Hash.c

@@ -16,168 +16,82 @@ enum {
     PIKA_HASHLIB_SHA512 = 64
 } pika_hashlib_t;
 
-void to_hex(uint8_t* s, int l, uint8_t* d);
+static void hashlib_to_hex(uint8_t* s, int l, uint8_t* d);
 
-void _hashlib_Hash_md5(PikaObj* self, Arg* data) {
-    ArgType t = arg_getType(data);
+void _hashlib_Hash_new(PikaObj* self, char* mode, Arg* data) {
+    ArgType t;
+    t = arg_getType(data);
     if (ARG_TYPE_NONE != t) {
         if (ARG_TYPE_BYTES != t) {
             obj_setErrorCode(self, -2);  // io error
         }
     }
 
-    size_t size = arg_getBytesSize(data);
-    uint8_t* data_h = arg_getBytes(data);
-
-    mbedtls_md5_context context;
-    mbedtls_md5_init(&context);
-    mbedtls_md5_starts(&context);
-    if (size != 0) {
-        mbedtls_md5_update(&context, data_h, size);
-    }
-    obj_setStruct(self, "context", context);
-    obj_setInt(self, "mode", PIKA_HASHLIB_MD5);
-}
-
-void _hashlib_Hash_sha1(PikaObj* self, Arg* data) {
-    ArgType t = arg_getType(data);
-    if (ARG_TYPE_NONE != t) {
-        if (ARG_TYPE_BYTES != t) {
-            obj_setErrorCode(self, -2);  // io error
-        }
-    }
-
-    size_t size = arg_getBytesSize(data);
-    uint8_t* data_h = arg_getBytes(data);
-
-    mbedtls_sha1_context context;
-    mbedtls_sha1_init(&context);
-    mbedtls_sha1_starts(&context);
-    if (size != 0) {
-        mbedtls_sha1_update(&context, data_h, size);
-    }
-    obj_setStruct(self, "context", context);
-    obj_setInt(self, "mode", PIKA_HASHLIB_SHA1);
-}
-
-void _hashlib_Hash_sha224(PikaObj* self, Arg* data) {
-    ArgType t = arg_getType(data);
-    if (ARG_TYPE_NONE != t) {
-        if (ARG_TYPE_BYTES != t) {
-            obj_setErrorCode(self, -2);  // io error
-        }
-    }
-    size_t size = arg_getBytesSize(data);
-    uint8_t* data_h = arg_getBytes(data);
-
-    mbedtls_sha256_context context;
-    mbedtls_sha256_init(&context);
-    mbedtls_sha256_starts(&context, 1);
-    if (size != 0) {
-        mbedtls_sha256_update(&context, data_h, size);
-    }
-    obj_setStruct(self, "context", context);
-    obj_setInt(self, "mode", PIKA_HASHLIB_SHA224);
-}
-
-void _hashlib_Hash_sha256(PikaObj* self, Arg* data) {
-    ArgType t = arg_getType(data);
-    if (ARG_TYPE_NONE != t) {
-        if (ARG_TYPE_BYTES != t) {
-            obj_setErrorCode(self, -2);  // io error
-        }
-    }
-
-    size_t size = arg_getBytesSize(data);
-    uint8_t* data_h = arg_getBytes(data);
-
-    mbedtls_sha256_context context;
-    mbedtls_sha256_init(&context);
-    mbedtls_sha256_starts(&context, 0);
-    if (size != 0) {
-        mbedtls_sha256_update(&context, data_h, size);
-    }
-    obj_setStruct(self, "context", context);
-    obj_setInt(self, "mode", PIKA_HASHLIB_SHA256);
-}
+    obj_setInt(self, "_digest_flags", 0);                    // flag
+    obj_setBytes(self, "_buff", NULL, PIKA_HASHLIB_SHA512);  // digest buff
+    obj_setBytes(self, "_hexbuff", NULL,
+                 PIKA_HASHLIB_SHA512 * 2);  // hexdigest buff
 
-void _hashlib_Hash_sha384(PikaObj* self, Arg* data) {
-    ArgType t = arg_getType(data);
-    if (ARG_TYPE_NONE != t) {
-        if (ARG_TYPE_BYTES != t) {
-            obj_setErrorCode(self, -2);  // io error
-        }
-    }
-
-    size_t size = arg_getBytesSize(data);
+    size_t data_len = arg_getBytesSize(data);
     uint8_t* data_h = arg_getBytes(data);
 
-    mbedtls_sha512_context context;
-    mbedtls_sha512_init(&context);
-    mbedtls_sha512_starts(&context, 1);
-    if (size != 0) {
-        mbedtls_sha512_update(&context, data_h, size);
-    }
-    obj_setStruct(self, "context", context);
-    obj_setInt(self, "mode", PIKA_HASHLIB_SHA384);
-}
-
-void _hashlib_Hash_sha512(PikaObj* self, Arg* data) {
-    ArgType t = arg_getType(data);
-    if (ARG_TYPE_NONE != t) {
-        if (ARG_TYPE_BYTES != t) {
-            obj_setErrorCode(self, -2);  // io error
-        }
-    }
-
-    size_t size = arg_getBytesSize(data);
-    uint8_t* data_h = arg_getBytes(data);
-
-    mbedtls_sha512_context context;
-    mbedtls_sha512_init(&context);
-    mbedtls_sha512_starts(&context, 0);
-    if (size != 0) {
-        mbedtls_sha512_update(&context, data_h, size);
-    }
-    obj_setStruct(self, "context", context);
-    obj_setInt(self, "mode", PIKA_HASHLIB_SHA512);
-}
-
-void _hashlib_Hash_new(PikaObj* self, char* mode) {
     if (strcmp(mode, "md5") == 0 || strcmp(mode, "MD5") == 0) {
         mbedtls_md5_context context;
         mbedtls_md5_init(&context);
         mbedtls_md5_starts(&context);
+        if (data_len > 0) {
+            mbedtls_md5_update(&context, data_h, data_len);
+        }
         obj_setStruct(self, "context", context);
         obj_setInt(self, "mode", PIKA_HASHLIB_MD5);
     } else if (strcmp(mode, "sha1") == 0 || strcmp(mode, "SHA1") == 0) {
         mbedtls_sha1_context context;
         mbedtls_sha1_init(&context);
         mbedtls_sha1_starts(&context);
+        if (data_len > 0) {
+            mbedtls_sha1_update(&context, data_h,
+                                data_len);
+        }
         obj_setStruct(self, "context", context);
         obj_setInt(self, "mode", PIKA_HASHLIB_SHA1);
     } else if (strcmp(mode, "sha224") == 0 || strcmp(mode, "SHA224") == 0) {
         mbedtls_sha256_context context;
         mbedtls_sha256_init(&context);
         mbedtls_sha256_starts(&context, 1);
+        if (data_len > 0) {
+            mbedtls_sha256_update(&context, data_h,
+                                  data_len);
+        }
         obj_setStruct(self, "context", context);
         obj_setInt(self, "mode", PIKA_HASHLIB_SHA224);
     } else if (strcmp(mode, "sha256") == 0 || strcmp(mode, "SHA256") == 0) {
         mbedtls_sha256_context context;
         mbedtls_sha256_init(&context);
         mbedtls_sha256_starts(&context, 0);
+        if (data_len > 0) {
+            mbedtls_sha256_update(&context, data_h,
+                                  data_len);
+        }
         obj_setStruct(self, "context", context);
         obj_setInt(self, "mode", PIKA_HASHLIB_SHA256);
     } else if (strcmp(mode, "sha384") == 0 || strcmp(mode, "SHA384") == 0) {
         mbedtls_sha512_context context;
         mbedtls_sha512_init(&context);
         mbedtls_sha512_starts(&context, 1);
+        if (data_len > 0) {
+            mbedtls_sha512_update(&context, data_h,
+                                  data_len);
+        }
         obj_setStruct(self, "context", context);
         obj_setInt(self, "mode", PIKA_HASHLIB_SHA384);
     } else if (strcmp(mode, "sha512") == 0 || strcmp(mode, "SHA512") == 0) {
         mbedtls_sha512_context context;
         mbedtls_sha512_init(&context);
         mbedtls_sha512_starts(&context, 0);
+        if (data_len > 0) {
+            mbedtls_sha512_update(&context, data_h,
+                                  data_len);
+        }
         obj_setStruct(self, "context", context);
         obj_setInt(self, "mode", PIKA_HASHLIB_SHA512);
     } else {
@@ -190,28 +104,29 @@ void _hashlib_Hash_update(PikaObj* self, Arg* data) {
         obj_setErrorCode(self, -2);  // io error
     }
 
-    size_t size = arg_getBytesSize(data);
+    void* context = obj_getStruct(self, "context");
+    size_t data_len = arg_getBytesSize(data);
     uint8_t* data_h = arg_getBytes(data);
 
-    if (size != 0) {
-        void* context = obj_getStruct(self, "context");
+    if (data_len > 0) {
         switch (obj_getInt(self, "mode")) {
             case PIKA_HASHLIB_MD5:
-                mbedtls_md5_update((mbedtls_md5_context*)context, data_h, size);
+                mbedtls_md5_update((mbedtls_md5_context*)context, data_h,
+                                   data_len);
                 break;
             case PIKA_HASHLIB_SHA1:
                 mbedtls_sha1_update((mbedtls_sha1_context*)context, data_h,
-                                    size);
+                                    data_len);
                 break;
             case PIKA_HASHLIB_SHA224:
             case PIKA_HASHLIB_SHA256:
                 mbedtls_sha256_update((mbedtls_sha256_context*)context, data_h,
-                                      size);
+                                      data_len);
                 break;
             case PIKA_HASHLIB_SHA384:
             case PIKA_HASHLIB_SHA512:
                 mbedtls_sha512_update((mbedtls_sha512_context*)context, data_h,
-                                      size);
+                                      data_len);
                 break;
             default:
                 obj_setErrorCode(self, -1);  // not support mode
@@ -223,52 +138,57 @@ void _hashlib_Hash_update(PikaObj* self, Arg* data) {
 }
 
 Arg* _hashlib_Hash_digest(PikaObj* self) {
-    obj_setBytes(self, "buff", NULL, 64);
-    uint8_t* buff = obj_getBytes(self, "buff");
-    void* context = obj_getStruct(self, "context");
+    uint8_t* buff = obj_getBytes(self, "_buff");
+    uint8_t flag = obj_getInt(self, "_digest_flags");
+
+    if (flag & 0x01)  // already digest
+    {
+        return arg_newBytes(buff, obj_getInt(self, "mode"));
+    } else {
+        void* context = obj_getStruct(self, "context");
+        uint8_t mode = obj_getInt(self, "mode");
 
-    switch (obj_getInt(self, "mode")) {
-        case PIKA_HASHLIB_MD5:
-            mbedtls_md5_finish((mbedtls_md5_context*)context, buff);
-            return arg_newBytes(buff, PIKA_HASHLIB_MD5);
-            break;
-        case PIKA_HASHLIB_SHA1:
-            mbedtls_sha1_finish((mbedtls_sha1_context*)context, buff);
-            return arg_newBytes(buff, PIKA_HASHLIB_SHA1);
-            break;
-        case PIKA_HASHLIB_SHA224:
-            mbedtls_sha256_finish((mbedtls_sha256_context*)context, buff);
-            return arg_newBytes(buff, PIKA_HASHLIB_SHA224);
-            break;
-        case PIKA_HASHLIB_SHA256:
-            mbedtls_sha256_finish((mbedtls_sha256_context*)context, buff);
-            return arg_newBytes(buff, PIKA_HASHLIB_SHA256);
-            break;
-        case PIKA_HASHLIB_SHA384:
-            mbedtls_sha512_finish((mbedtls_sha512_context*)context, buff);
-            return arg_newBytes(buff, PIKA_HASHLIB_SHA384);
-            break;
-        case PIKA_HASHLIB_SHA512:
-            mbedtls_sha512_finish((mbedtls_sha512_context*)context, buff);
-            return arg_newBytes(buff, PIKA_HASHLIB_SHA512);
-            break;
-        default:
-            obj_setErrorCode(self, -1);  // not support mode
-            return arg_newNull();
-            break;
+        switch (mode) {
+            case PIKA_HASHLIB_MD5:
+                mbedtls_md5_finish((mbedtls_md5_context*)context, buff);
+                break;
+            case PIKA_HASHLIB_SHA1:
+                mbedtls_sha1_finish((mbedtls_sha1_context*)context, buff);
+                break;
+            case PIKA_HASHLIB_SHA224:
+                mbedtls_sha256_finish((mbedtls_sha256_context*)context, buff);
+                break;
+            case PIKA_HASHLIB_SHA256:
+                mbedtls_sha256_finish((mbedtls_sha256_context*)context, buff);
+                break;
+            case PIKA_HASHLIB_SHA384:
+                mbedtls_sha512_finish((mbedtls_sha512_context*)context, buff);
+                break;
+            case PIKA_HASHLIB_SHA512:
+                mbedtls_sha512_finish((mbedtls_sha512_context*)context, buff);
+                break;
+            default:
+                obj_setErrorCode(self, -1);  // not support mode
+                return arg_newNull();  // will not actually return to the python
+                break;
+        }
+        obj_setInt(self, "_digest_flags", flag | 0x01);
+        return arg_newBytes(buff, mode);
     }
 }
 
 char* _hashlib_Hash_hexdigest(PikaObj* self) {
-    obj_setBytes(self, "hexbuff", NULL, 128);
-    uint8_t* hexbuff = obj_getBytes(self, "hexbuff");
-    uint8_t* buff = obj_getBytes(self, "buff");
+    uint8_t* hexbuff = obj_getBytes(self, "_hexbuff");
+    uint8_t* buff = obj_getBytes(self, "_buff");
+    uint8_t flag = obj_getInt(self, "_digest_flags");
 
-    if (buff == NULL) {
-        obj_setBytes(self, "buff", NULL, 64);
-        uint8_t* buff = obj_getBytes(self, "buff");
-        void* context = obj_getStruct(self, "context");
+    if (flag & 0x01) {  // already digest
+        hashlib_to_hex(buff, obj_getInt(self, "mode"), hexbuff);
+        obj_setInt(self, "_digest_flags", flag | 0x02);  // set hexdigest flag
+    } else if (flag & 0x02) {                           // already hexdigest
 
+    } else {
+        void* context = obj_getStruct(self, "context");
         switch (obj_getInt(self, "mode")) {
             case PIKA_HASHLIB_MD5:
                 mbedtls_md5_finish((mbedtls_md5_context*)context, buff);
@@ -292,20 +212,22 @@ char* _hashlib_Hash_hexdigest(PikaObj* self) {
                 obj_setErrorCode(self, -1);  // not support mode
                 break;
         }
-        to_hex(buff, obj_getInt(self, "mode"), hexbuff);
-    } else {
-        to_hex(buff, obj_getInt(self, "mode"), hexbuff);
+        hashlib_to_hex(buff, obj_getInt(self, "mode"), hexbuff);
+        obj_setInt(self, "_digest_flags",
+                   flag | 0x03);  // set digest and hexdigest flags
     }
     return (char*)hexbuff;
 }
 
-void _hashlib_Hash_copy(PikaObj* self) {}
+void _hashlib_Hash_copy(PikaObj* self) {  // todo
+}
 
-const uint8_t hex_table[] = {'0', '1', '2', '3', '4', '5', '6', '7',
-                             '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
-void to_hex(uint8_t* s, int l, uint8_t* d) {
+static const uint8_t hashlib_hex_table[] = {'0', '1', '2', '3', '4', '5',
+                                            '6', '7', '8', '9', 'A', 'B',
+                                            'C', 'D', 'E', 'F'};
+static void hashlib_to_hex(uint8_t* s, int l, uint8_t* d) {
     while (l--) {
-        *(d++) = hex_table[*s >> 4];
-        *(d++) = hex_table[*(s++) & 0x0f];
+        *(d++) = hashlib_hex_table[*s >> 4];
+        *(d++) = hashlib_hex_table[*(s++) & 0x0f];
     }
 }

+ 7 - 7
package/hashlib/hashlib.py

@@ -3,41 +3,41 @@ import _hashlib
 
 def new(mode: str) -> _hashlib.Hash:
     hash = _hashlib.Hash()
-    hash.new(mode)
+    hash.new(mode, None)
     return hash
 
 
 def md5(data = None) -> _hashlib.Hash:
     hash = _hashlib.Hash()
-    hash.md5(data)
+    hash.new("md5", data)
     return hash
 
 
 def sha1(data = None) -> _hashlib.Hash:
     hash = _hashlib.Hash()
-    hash.sha1(data)
+    hash.new("sha1", data)
     return hash
 
 
 def sha224(data = None) -> _hashlib.Hash:
     hash = _hashlib.Hash()
-    hash.sha224(data)
+    hash.new("sha224", data)
     return hash
 
 
 def sha256(data = None) -> _hashlib.Hash:
     hash = _hashlib.Hash()
-    hash.sha256(data)
+    hash.new("sha256", data)
     return hash
 
 
 def sha384(data = None) -> _hashlib.Hash:
     hash = _hashlib.Hash()
-    hash.sha384(data)
+    hash.new("sha384", data)
     return hash
 
 
 def sha512(data = None) -> _hashlib.Hash:
     hash = _hashlib.Hash()
-    hash.sha512(data)
+    hash.new("sha512", data)
     return hash

+ 1 - 7
port/linux/package/pikascript/_hashlib.pyi

@@ -1,11 +1,5 @@
 class Hash:
-    def new(self, mode: str): ...
-    def md5(self, data: any): ...
-    def sha1(self, data: any): ...
-    def sha224(self, data: any): ...
-    def sha256(self, data: any): ...
-    def sha384(self, data: any): ...
-    def sha512(self, data: any): ...
+    def new(self, mode: str, data:any): ...
     def update(self, data: any): ...
     def digest(self) -> any: ...
     def hexdigest(self) -> str: ...

+ 7 - 7
port/linux/package/pikascript/hashlib.py

@@ -3,41 +3,41 @@ import _hashlib
 
 def new(mode: str) -> _hashlib.Hash:
     hash = _hashlib.Hash()
-    hash.new(mode)
+    hash.new(mode, None)
     return hash
 
 
 def md5(data = None) -> _hashlib.Hash:
     hash = _hashlib.Hash()
-    hash.md5(data)
+    hash.new("md5", data)
     return hash
 
 
 def sha1(data = None) -> _hashlib.Hash:
     hash = _hashlib.Hash()
-    hash.sha1(data)
+    hash.new("sha1", data)
     return hash
 
 
 def sha224(data = None) -> _hashlib.Hash:
     hash = _hashlib.Hash()
-    hash.sha224(data)
+    hash.new("sha224", data)
     return hash
 
 
 def sha256(data = None) -> _hashlib.Hash:
     hash = _hashlib.Hash()
-    hash.sha256(data)
+    hash.new("sha256", data)
     return hash
 
 
 def sha384(data = None) -> _hashlib.Hash:
     hash = _hashlib.Hash()
-    hash.sha384(data)
+    hash.new("sha384", data)
     return hash
 
 
 def sha512(data = None) -> _hashlib.Hash:
     hash = _hashlib.Hash()
-    hash.sha512(data)
+    hash.new("sha512", data)
     return hash

+ 95 - 173
port/linux/package/pikascript/pikascript-lib/hashlib/_hashlib_Hash.c

@@ -16,168 +16,82 @@ enum {
     PIKA_HASHLIB_SHA512 = 64
 } pika_hashlib_t;
 
-void to_hex(uint8_t* s, int l, uint8_t* d);
+static void hashlib_to_hex(uint8_t* s, int l, uint8_t* d);
 
-void _hashlib_Hash_md5(PikaObj* self, Arg* data) {
-    ArgType t = arg_getType(data);
+void _hashlib_Hash_new(PikaObj* self, char* mode, Arg* data) {
+    ArgType t;
+    t = arg_getType(data);
     if (ARG_TYPE_NONE != t) {
         if (ARG_TYPE_BYTES != t) {
             obj_setErrorCode(self, -2);  // io error
         }
     }
 
-    size_t size = arg_getBytesSize(data);
-    uint8_t* data_h = arg_getBytes(data);
-
-    mbedtls_md5_context context;
-    mbedtls_md5_init(&context);
-    mbedtls_md5_starts(&context);
-    if (size != 0) {
-        mbedtls_md5_update(&context, data_h, size);
-    }
-    obj_setStruct(self, "context", context);
-    obj_setInt(self, "mode", PIKA_HASHLIB_MD5);
-}
-
-void _hashlib_Hash_sha1(PikaObj* self, Arg* data) {
-    ArgType t = arg_getType(data);
-    if (ARG_TYPE_NONE != t) {
-        if (ARG_TYPE_BYTES != t) {
-            obj_setErrorCode(self, -2);  // io error
-        }
-    }
-
-    size_t size = arg_getBytesSize(data);
-    uint8_t* data_h = arg_getBytes(data);
-
-    mbedtls_sha1_context context;
-    mbedtls_sha1_init(&context);
-    mbedtls_sha1_starts(&context);
-    if (size != 0) {
-        mbedtls_sha1_update(&context, data_h, size);
-    }
-    obj_setStruct(self, "context", context);
-    obj_setInt(self, "mode", PIKA_HASHLIB_SHA1);
-}
-
-void _hashlib_Hash_sha224(PikaObj* self, Arg* data) {
-    ArgType t = arg_getType(data);
-    if (ARG_TYPE_NONE != t) {
-        if (ARG_TYPE_BYTES != t) {
-            obj_setErrorCode(self, -2);  // io error
-        }
-    }
-    size_t size = arg_getBytesSize(data);
-    uint8_t* data_h = arg_getBytes(data);
-
-    mbedtls_sha256_context context;
-    mbedtls_sha256_init(&context);
-    mbedtls_sha256_starts(&context, 1);
-    if (size != 0) {
-        mbedtls_sha256_update(&context, data_h, size);
-    }
-    obj_setStruct(self, "context", context);
-    obj_setInt(self, "mode", PIKA_HASHLIB_SHA224);
-}
-
-void _hashlib_Hash_sha256(PikaObj* self, Arg* data) {
-    ArgType t = arg_getType(data);
-    if (ARG_TYPE_NONE != t) {
-        if (ARG_TYPE_BYTES != t) {
-            obj_setErrorCode(self, -2);  // io error
-        }
-    }
-
-    size_t size = arg_getBytesSize(data);
-    uint8_t* data_h = arg_getBytes(data);
-
-    mbedtls_sha256_context context;
-    mbedtls_sha256_init(&context);
-    mbedtls_sha256_starts(&context, 0);
-    if (size != 0) {
-        mbedtls_sha256_update(&context, data_h, size);
-    }
-    obj_setStruct(self, "context", context);
-    obj_setInt(self, "mode", PIKA_HASHLIB_SHA256);
-}
+    obj_setInt(self, "_digest_flags", 0);                    // flag
+    obj_setBytes(self, "_buff", NULL, PIKA_HASHLIB_SHA512);  // digest buff
+    obj_setBytes(self, "_hexbuff", NULL,
+                 PIKA_HASHLIB_SHA512 * 2);  // hexdigest buff
 
-void _hashlib_Hash_sha384(PikaObj* self, Arg* data) {
-    ArgType t = arg_getType(data);
-    if (ARG_TYPE_NONE != t) {
-        if (ARG_TYPE_BYTES != t) {
-            obj_setErrorCode(self, -2);  // io error
-        }
-    }
-
-    size_t size = arg_getBytesSize(data);
+    size_t data_len = arg_getBytesSize(data);
     uint8_t* data_h = arg_getBytes(data);
 
-    mbedtls_sha512_context context;
-    mbedtls_sha512_init(&context);
-    mbedtls_sha512_starts(&context, 1);
-    if (size != 0) {
-        mbedtls_sha512_update(&context, data_h, size);
-    }
-    obj_setStruct(self, "context", context);
-    obj_setInt(self, "mode", PIKA_HASHLIB_SHA384);
-}
-
-void _hashlib_Hash_sha512(PikaObj* self, Arg* data) {
-    ArgType t = arg_getType(data);
-    if (ARG_TYPE_NONE != t) {
-        if (ARG_TYPE_BYTES != t) {
-            obj_setErrorCode(self, -2);  // io error
-        }
-    }
-
-    size_t size = arg_getBytesSize(data);
-    uint8_t* data_h = arg_getBytes(data);
-
-    mbedtls_sha512_context context;
-    mbedtls_sha512_init(&context);
-    mbedtls_sha512_starts(&context, 0);
-    if (size != 0) {
-        mbedtls_sha512_update(&context, data_h, size);
-    }
-    obj_setStruct(self, "context", context);
-    obj_setInt(self, "mode", PIKA_HASHLIB_SHA512);
-}
-
-void _hashlib_Hash_new(PikaObj* self, char* mode) {
     if (strcmp(mode, "md5") == 0 || strcmp(mode, "MD5") == 0) {
         mbedtls_md5_context context;
         mbedtls_md5_init(&context);
         mbedtls_md5_starts(&context);
+        if (data_len > 0) {
+            mbedtls_md5_update(&context, data_h, data_len);
+        }
         obj_setStruct(self, "context", context);
         obj_setInt(self, "mode", PIKA_HASHLIB_MD5);
     } else if (strcmp(mode, "sha1") == 0 || strcmp(mode, "SHA1") == 0) {
         mbedtls_sha1_context context;
         mbedtls_sha1_init(&context);
         mbedtls_sha1_starts(&context);
+        if (data_len > 0) {
+            mbedtls_sha1_update(&context, data_h,
+                                data_len);
+        }
         obj_setStruct(self, "context", context);
         obj_setInt(self, "mode", PIKA_HASHLIB_SHA1);
     } else if (strcmp(mode, "sha224") == 0 || strcmp(mode, "SHA224") == 0) {
         mbedtls_sha256_context context;
         mbedtls_sha256_init(&context);
         mbedtls_sha256_starts(&context, 1);
+        if (data_len > 0) {
+            mbedtls_sha256_update(&context, data_h,
+                                  data_len);
+        }
         obj_setStruct(self, "context", context);
         obj_setInt(self, "mode", PIKA_HASHLIB_SHA224);
     } else if (strcmp(mode, "sha256") == 0 || strcmp(mode, "SHA256") == 0) {
         mbedtls_sha256_context context;
         mbedtls_sha256_init(&context);
         mbedtls_sha256_starts(&context, 0);
+        if (data_len > 0) {
+            mbedtls_sha256_update(&context, data_h,
+                                  data_len);
+        }
         obj_setStruct(self, "context", context);
         obj_setInt(self, "mode", PIKA_HASHLIB_SHA256);
     } else if (strcmp(mode, "sha384") == 0 || strcmp(mode, "SHA384") == 0) {
         mbedtls_sha512_context context;
         mbedtls_sha512_init(&context);
         mbedtls_sha512_starts(&context, 1);
+        if (data_len > 0) {
+            mbedtls_sha512_update(&context, data_h,
+                                  data_len);
+        }
         obj_setStruct(self, "context", context);
         obj_setInt(self, "mode", PIKA_HASHLIB_SHA384);
     } else if (strcmp(mode, "sha512") == 0 || strcmp(mode, "SHA512") == 0) {
         mbedtls_sha512_context context;
         mbedtls_sha512_init(&context);
         mbedtls_sha512_starts(&context, 0);
+        if (data_len > 0) {
+            mbedtls_sha512_update(&context, data_h,
+                                  data_len);
+        }
         obj_setStruct(self, "context", context);
         obj_setInt(self, "mode", PIKA_HASHLIB_SHA512);
     } else {
@@ -190,28 +104,29 @@ void _hashlib_Hash_update(PikaObj* self, Arg* data) {
         obj_setErrorCode(self, -2);  // io error
     }
 
-    size_t size = arg_getBytesSize(data);
+    void* context = obj_getStruct(self, "context");
+    size_t data_len = arg_getBytesSize(data);
     uint8_t* data_h = arg_getBytes(data);
 
-    if (size != 0) {
-        void* context = obj_getStruct(self, "context");
+    if (data_len > 0) {
         switch (obj_getInt(self, "mode")) {
             case PIKA_HASHLIB_MD5:
-                mbedtls_md5_update((mbedtls_md5_context*)context, data_h, size);
+                mbedtls_md5_update((mbedtls_md5_context*)context, data_h,
+                                   data_len);
                 break;
             case PIKA_HASHLIB_SHA1:
                 mbedtls_sha1_update((mbedtls_sha1_context*)context, data_h,
-                                    size);
+                                    data_len);
                 break;
             case PIKA_HASHLIB_SHA224:
             case PIKA_HASHLIB_SHA256:
                 mbedtls_sha256_update((mbedtls_sha256_context*)context, data_h,
-                                      size);
+                                      data_len);
                 break;
             case PIKA_HASHLIB_SHA384:
             case PIKA_HASHLIB_SHA512:
                 mbedtls_sha512_update((mbedtls_sha512_context*)context, data_h,
-                                      size);
+                                      data_len);
                 break;
             default:
                 obj_setErrorCode(self, -1);  // not support mode
@@ -223,52 +138,57 @@ void _hashlib_Hash_update(PikaObj* self, Arg* data) {
 }
 
 Arg* _hashlib_Hash_digest(PikaObj* self) {
-    obj_setBytes(self, "buff", NULL, 64);
-    uint8_t* buff = obj_getBytes(self, "buff");
-    void* context = obj_getStruct(self, "context");
+    uint8_t* buff = obj_getBytes(self, "_buff");
+    uint8_t flag = obj_getInt(self, "_digest_flags");
+
+    if (flag & 0x01)  // already digest
+    {
+        return arg_newBytes(buff, obj_getInt(self, "mode"));
+    } else {
+        void* context = obj_getStruct(self, "context");
+        uint8_t mode = obj_getInt(self, "mode");
 
-    switch (obj_getInt(self, "mode")) {
-        case PIKA_HASHLIB_MD5:
-            mbedtls_md5_finish((mbedtls_md5_context*)context, buff);
-            return arg_newBytes(buff, PIKA_HASHLIB_MD5);
-            break;
-        case PIKA_HASHLIB_SHA1:
-            mbedtls_sha1_finish((mbedtls_sha1_context*)context, buff);
-            return arg_newBytes(buff, PIKA_HASHLIB_SHA1);
-            break;
-        case PIKA_HASHLIB_SHA224:
-            mbedtls_sha256_finish((mbedtls_sha256_context*)context, buff);
-            return arg_newBytes(buff, PIKA_HASHLIB_SHA224);
-            break;
-        case PIKA_HASHLIB_SHA256:
-            mbedtls_sha256_finish((mbedtls_sha256_context*)context, buff);
-            return arg_newBytes(buff, PIKA_HASHLIB_SHA256);
-            break;
-        case PIKA_HASHLIB_SHA384:
-            mbedtls_sha512_finish((mbedtls_sha512_context*)context, buff);
-            return arg_newBytes(buff, PIKA_HASHLIB_SHA384);
-            break;
-        case PIKA_HASHLIB_SHA512:
-            mbedtls_sha512_finish((mbedtls_sha512_context*)context, buff);
-            return arg_newBytes(buff, PIKA_HASHLIB_SHA512);
-            break;
-        default:
-            obj_setErrorCode(self, -1);  // not support mode
-            return arg_newNull();
-            break;
+        switch (mode) {
+            case PIKA_HASHLIB_MD5:
+                mbedtls_md5_finish((mbedtls_md5_context*)context, buff);
+                break;
+            case PIKA_HASHLIB_SHA1:
+                mbedtls_sha1_finish((mbedtls_sha1_context*)context, buff);
+                break;
+            case PIKA_HASHLIB_SHA224:
+                mbedtls_sha256_finish((mbedtls_sha256_context*)context, buff);
+                break;
+            case PIKA_HASHLIB_SHA256:
+                mbedtls_sha256_finish((mbedtls_sha256_context*)context, buff);
+                break;
+            case PIKA_HASHLIB_SHA384:
+                mbedtls_sha512_finish((mbedtls_sha512_context*)context, buff);
+                break;
+            case PIKA_HASHLIB_SHA512:
+                mbedtls_sha512_finish((mbedtls_sha512_context*)context, buff);
+                break;
+            default:
+                obj_setErrorCode(self, -1);  // not support mode
+                return arg_newNull();  // will not actually return to the python
+                break;
+        }
+        obj_setInt(self, "_digest_flags", flag | 0x01);
+        return arg_newBytes(buff, mode);
     }
 }
 
 char* _hashlib_Hash_hexdigest(PikaObj* self) {
-    obj_setBytes(self, "hexbuff", NULL, 128);
-    uint8_t* hexbuff = obj_getBytes(self, "hexbuff");
-    uint8_t* buff = obj_getBytes(self, "buff");
+    uint8_t* hexbuff = obj_getBytes(self, "_hexbuff");
+    uint8_t* buff = obj_getBytes(self, "_buff");
+    uint8_t flag = obj_getInt(self, "_digest_flags");
 
-    if (buff == NULL) {
-        obj_setBytes(self, "buff", NULL, 64);
-        uint8_t* buff = obj_getBytes(self, "buff");
-        void* context = obj_getStruct(self, "context");
+    if (flag & 0x01) {  // already digest
+        hashlib_to_hex(buff, obj_getInt(self, "mode"), hexbuff);
+        obj_setInt(self, "_digest_flags", flag | 0x02);  // set hexdigest flag
+    } else if (flag & 0x02) {                           // already hexdigest
 
+    } else {
+        void* context = obj_getStruct(self, "context");
         switch (obj_getInt(self, "mode")) {
             case PIKA_HASHLIB_MD5:
                 mbedtls_md5_finish((mbedtls_md5_context*)context, buff);
@@ -292,20 +212,22 @@ char* _hashlib_Hash_hexdigest(PikaObj* self) {
                 obj_setErrorCode(self, -1);  // not support mode
                 break;
         }
-        to_hex(buff, obj_getInt(self, "mode"), hexbuff);
-    } else {
-        to_hex(buff, obj_getInt(self, "mode"), hexbuff);
+        hashlib_to_hex(buff, obj_getInt(self, "mode"), hexbuff);
+        obj_setInt(self, "_digest_flags",
+                   flag | 0x03);  // set digest and hexdigest flags
     }
     return (char*)hexbuff;
 }
 
-void _hashlib_Hash_copy(PikaObj* self) {}
+void _hashlib_Hash_copy(PikaObj* self) {  // todo
+}
 
-const uint8_t hex_table[] = {'0', '1', '2', '3', '4', '5', '6', '7',
-                             '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
-void to_hex(uint8_t* s, int l, uint8_t* d) {
+static const uint8_t hashlib_hex_table[] = {'0', '1', '2', '3', '4', '5',
+                                            '6', '7', '8', '9', 'A', 'B',
+                                            'C', 'D', 'E', 'F'};
+static void hashlib_to_hex(uint8_t* s, int l, uint8_t* d) {
     while (l--) {
-        *(d++) = hex_table[*s >> 4];
-        *(d++) = hex_table[*(s++) & 0x0f];
+        *(d++) = hashlib_hex_table[*s >> 4];
+        *(d++) = hashlib_hex_table[*(s++) & 0x0f];
     }
 }