mirror of
https://github.com/haiwen/seafile-server.git
synced 2025-04-28 03:20:10 +00:00
Use c to unmarshal json and decompress data
This commit is contained in:
parent
9debeec57e
commit
9d7e82a883
@ -284,25 +284,6 @@ func NewSeafile(version int, fileSize int64, blkIDs []string) (*Seafile, error)
|
||||
return seafile, nil
|
||||
}
|
||||
|
||||
func uncompress(p []byte) ([]byte, error) {
|
||||
b := bytes.NewReader(p)
|
||||
var out bytes.Buffer
|
||||
r, err := zlib.NewReader(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = io.Copy(&out, r)
|
||||
if err != nil {
|
||||
r.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r.Close()
|
||||
|
||||
return out.Bytes(), nil
|
||||
}
|
||||
|
||||
func compress(p []byte) ([]byte, error) {
|
||||
var out bytes.Buffer
|
||||
w := zlib.NewWriter(&out)
|
||||
@ -324,7 +305,7 @@ func (seafile *Seafile) FromData(p []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = json.Unmarshal(b, seafile)
|
||||
err = seafile.unmarshal(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -368,7 +349,7 @@ func (seafdir *SeafDir) FromData(p []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = json.Unmarshal(b, seafdir)
|
||||
err = seafdir.unmarshal(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
210
fileserver/fsmgr/fsmgr_c.go
Normal file
210
fileserver/fsmgr/fsmgr_c.go
Normal file
@ -0,0 +1,210 @@
|
||||
package fsmgr
|
||||
|
||||
/*#cgo pkg-config: zlib jansson glib-2.0
|
||||
#include <stdio.h>
|
||||
#include <glib.h>
|
||||
#include <zlib.h>
|
||||
#include <jansson.h>
|
||||
|
||||
#define ZLIB_BUF_SIZE 16384
|
||||
|
||||
int
|
||||
seaf_decompress (unsigned char *input, int inlen, unsigned char **output, int *outlen)
|
||||
{
|
||||
int ret;
|
||||
unsigned have;
|
||||
z_stream strm;
|
||||
unsigned char out[ZLIB_BUF_SIZE];
|
||||
GByteArray *barray;
|
||||
|
||||
if (inlen == 0) {
|
||||
g_warning ("Empty input for zlib, invalid.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
strm.avail_in = 0;
|
||||
strm.next_in = Z_NULL;
|
||||
ret = inflateInit(&strm);
|
||||
if (ret != Z_OK) {
|
||||
g_warning ("inflateInit failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strm.avail_in = inlen;
|
||||
strm.next_in = input;
|
||||
barray = g_byte_array_new ();
|
||||
|
||||
do {
|
||||
strm.avail_out = ZLIB_BUF_SIZE;
|
||||
strm.next_out = out;
|
||||
ret = inflate(&strm, Z_NO_FLUSH);
|
||||
if (ret < 0) {
|
||||
g_warning ("Failed to inflate.\n");
|
||||
goto out;
|
||||
}
|
||||
have = ZLIB_BUF_SIZE - strm.avail_out;
|
||||
g_byte_array_append (barray, out, have);
|
||||
} while (ret != Z_STREAM_END);
|
||||
|
||||
out:
|
||||
(void)inflateEnd(&strm);
|
||||
|
||||
if (ret == Z_STREAM_END) {
|
||||
*outlen = barray->len;
|
||||
*output = g_byte_array_free (barray, 0);
|
||||
return 0;
|
||||
} else {
|
||||
g_byte_array_free (barray, 1);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func (seafile *Seafile) unmarshal(b []byte) error {
|
||||
if b == nil || len(b) == 0 {
|
||||
err := fmt.Errorf("failed to load seafile json object")
|
||||
return err
|
||||
}
|
||||
object := C.json_loadb((*C.char)(unsafe.Pointer(&b[0])), C.ulong(len(b)), 0, nil)
|
||||
if unsafe.Pointer(object) == C.NULL {
|
||||
err := fmt.Errorf("failed to load seafile json object2")
|
||||
return err
|
||||
}
|
||||
|
||||
err := seafile.fillSeafileFromJsonObject(object)
|
||||
|
||||
C.json_decref(object)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (seafile *Seafile) fillSeafileFromJsonObject(object *C.json_t) error {
|
||||
seafile.Version = int(jsonGetIntMember(object, "version"))
|
||||
seafile.FileType = int(jsonGetIntMember(object, "type"))
|
||||
seafile.FileSize = uint64(jsonGetIntMember(object, "size"))
|
||||
seafile.FileID = jsonGetStringMember(object, "file_id")
|
||||
|
||||
cKey := C.CString("block_ids")
|
||||
block_id_array := C.json_object_get(object, cKey)
|
||||
C.free(unsafe.Pointer(cKey))
|
||||
if unsafe.Pointer(block_id_array) == C.NULL {
|
||||
err := fmt.Errorf("no block id array in seafile object")
|
||||
return err
|
||||
}
|
||||
n_blocks := C.json_array_size(block_id_array)
|
||||
|
||||
for i := 0; i < int(n_blocks); i++ {
|
||||
block_id_obj := C.json_array_get(block_id_array, C.ulong(i))
|
||||
block_id := C.json_string_value(block_id_obj)
|
||||
if unsafe.Pointer(block_id) == C.NULL {
|
||||
err := fmt.Errorf("no block id in block id array")
|
||||
return err
|
||||
}
|
||||
seafile.BlkIDs = append(seafile.BlkIDs, C.GoString(block_id))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (seafdir *SeafDir) unmarshal(b []byte) error {
|
||||
if b == nil || len(b) == 0 {
|
||||
err := fmt.Errorf("failed to load seafile json object")
|
||||
return err
|
||||
}
|
||||
object := C.json_loadb((*C.char)(unsafe.Pointer(&b[0])), C.ulong(len(b)), 0, nil)
|
||||
if unsafe.Pointer(object) == C.NULL {
|
||||
err := fmt.Errorf("failed to load seafile json object2")
|
||||
return err
|
||||
}
|
||||
|
||||
err := seafdir.fillSeaDirFromJsonObject(object)
|
||||
|
||||
C.json_decref(object)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (seafdir *SeafDir) fillSeaDirFromJsonObject(object *C.json_t) error {
|
||||
seafdir.Version = int(jsonGetIntMember(object, "version"))
|
||||
seafdir.DirType = int(jsonGetIntMember(object, "type"))
|
||||
seafdir.DirID = jsonGetStringMember(object, "dir_id")
|
||||
|
||||
cKey := C.CString("dirents")
|
||||
dirent_array := C.json_object_get(object, cKey)
|
||||
C.free(unsafe.Pointer(cKey))
|
||||
if unsafe.Pointer(dirent_array) == C.NULL {
|
||||
err := fmt.Errorf("no dirents in dir object")
|
||||
return err
|
||||
}
|
||||
n_dirents := C.json_array_size(dirent_array)
|
||||
|
||||
for i := 0; i < int(n_dirents); i++ {
|
||||
dirent_obj := C.json_array_get(dirent_array, C.ulong(i))
|
||||
if unsafe.Pointer(dirent_obj) == C.NULL {
|
||||
err := fmt.Errorf("no dirent in dirent array")
|
||||
return err
|
||||
}
|
||||
seafdir.fillSeafDirentFromJsonObject(dirent_obj)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (seafdir *SeafDir) fillSeafDirentFromJsonObject(object *C.json_t) {
|
||||
dirent := new(SeafDirent)
|
||||
dirent.Mode = uint32(jsonGetIntMember(object, "mode"))
|
||||
dirent.ID = jsonGetStringMember(object, "id")
|
||||
dirent.Name = jsonGetStringMember(object, "name")
|
||||
dirent.Mtime = jsonGetIntMember(object, "mtime")
|
||||
dirent.Modifier = jsonGetStringMember(object, "modifier")
|
||||
dirent.Size = jsonGetIntMember(object, "size")
|
||||
|
||||
seafdir.Entries = append(seafdir.Entries, dirent)
|
||||
}
|
||||
|
||||
func jsonGetIntMember(object *C.json_t, key string) int64 {
|
||||
cKey := C.CString(key)
|
||||
integer := C.json_object_get(object, cKey)
|
||||
C.free(unsafe.Pointer(cKey))
|
||||
return int64(C.json_integer_value(integer))
|
||||
}
|
||||
|
||||
func jsonGetStringMember(object *C.json_t, key string) string {
|
||||
cKey := C.CString(key)
|
||||
str := C.json_object_get(object, cKey)
|
||||
C.free(unsafe.Pointer(cKey))
|
||||
if unsafe.Pointer(str) == C.NULL {
|
||||
return C.GoString((*C.char)(C.NULL))
|
||||
}
|
||||
return C.GoString(C.json_string_value(str))
|
||||
}
|
||||
|
||||
func uncompress(p []byte) ([]byte, error) {
|
||||
var c_out *C.uchar
|
||||
var outlen C.int
|
||||
|
||||
if p == nil || len(p) == 0 {
|
||||
err := fmt.Errorf("empty input for zlib")
|
||||
return nil, err
|
||||
}
|
||||
ret := C.seaf_decompress((*C.uchar)(unsafe.Pointer(&p[0])), C.int(len(p)), &c_out, &outlen)
|
||||
if ret < 0 {
|
||||
err := fmt.Errorf("failed to uncompress data")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := []byte(C.GoStringN((*C.char)(unsafe.Pointer(c_out)), outlen))
|
||||
|
||||
C.free(unsafe.Pointer(c_out))
|
||||
|
||||
return out, nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user