File: cybase.pyx

package info (click to toggle)
python-thriftpy 0.3.9%2Bds1-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster
  • size: 560 kB
  • sloc: python: 3,287; ansic: 30; makefile: 7
file content (138 lines) | stat: -rw-r--r-- 3,538 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
from libc.stdlib cimport malloc, free
from libc.string cimport memcpy, memmove


cdef class TCyBuffer(object):
    def __cinit__(self, buf_size):
        self.buf = <char*>malloc(buf_size)
        self.buf_size = buf_size
        self.cur = 0
        self.data_size = 0

    def __dealloc__(self):
        if self.buf != NULL:
            free(self.buf)
            self.buf = NULL

    cdef void move_to_start(self):
        memmove(self.buf, self.buf + self.cur, self.data_size)
        self.cur = 0

    cdef void clean(self):
        self.cur = 0
        self.data_size = 0

    cdef int write(self, int sz, const char *value):
        cdef:
            int cap = self.buf_size - self.data_size
            int remain = cap - self.cur

        if sz <= 0:
            return 0

        if remain < sz:
            self.move_to_start()

        # recompute remain spaces
        remain = cap - self.cur

        if remain < sz:
            if self.grow(sz - remain + self.buf_size) != 0:
                return -1

        memcpy(self.buf + self.cur + self.data_size, value, sz)
        self.data_size += sz

        return sz

    cdef read_trans(self, trans, int sz, char *out):
        cdef int cap, new_data_len

        if sz <= 0:
            return 0

        if self.data_size < sz:
            if self.buf_size < sz:
                if self.grow(sz) != 0:
                    return -2  # grow buffer error

            cap = self.buf_size - self.data_size

            new_data = trans.read(cap)
            new_data_len = len(new_data)

            while new_data_len + self.data_size < sz:
                more = trans.read(cap - new_data_len)
                more_len = len(more)
                if more_len <= 0:
                    return -1  # end of file error

                new_data += more
                new_data_len += more_len

            if cap - self.cur < new_data_len:
                self.move_to_start()

            memcpy(self.buf + self.cur + self.data_size, <char*>new_data,
                   new_data_len)
            self.data_size += new_data_len

        memcpy(out, self.buf + self.cur, sz)
        self.cur += sz
        self.data_size -= sz

        return sz

    cdef int grow(self, int min_size):
        if min_size <= self.buf_size:
            return 0

        cdef int multiples = min_size / self.buf_size
        if min_size % self.buf_size != 0:
            multiples += 1

        cdef int new_size = self.buf_size * multiples
        cdef char *new_buf = <char*>malloc(new_size)
        if new_buf == NULL:
            return -1
        memcpy(new_buf + self.cur, self.buf + self.cur, self.data_size)
        free(self.buf)
        self.buf_size = new_size
        self.buf = new_buf
        return 0


cdef class CyTransportBase(object):
    cdef c_read(self, int sz, char* out):
        pass

    cdef c_write(self, char* data, int sz):
        pass

    cdef c_flush(self):
        pass

    def clean(self):
        pass

    @property
    def sock(self):
        if not self.trans:
            return
        return getattr(self.trans, 'sock', None)

    cdef get_string(self, int sz):
        cdef:
            char out[STACK_STRING_LEN]
            char *dy_out

        if sz > STACK_STRING_LEN:
            dy_out = <char*>malloc(sz)
            try:
                size = self.c_read(sz, dy_out)
                return dy_out[:size]
            finally:
                free(dy_out)
        else:
            size = self.c_read(sz, out)
            return out[:size]