Mercurial > vim
comparison src/blob.c @ 15454:1d2b5c016f17 v8.1.0735
patch 8.1.0735: cannot handle binary data
commit https://github.com/vim/vim/commit/6e5ea8d2a995b32bbc5972edc4f827b959f2702f
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Jan 12 22:47:31 2019 +0100
patch 8.1.0735: cannot handle binary data
Problem: Cannot handle binary data.
Solution: Add the Blob type. (Yasuhiro Matsumoto, closes https://github.com/vim/vim/issues/3638)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 12 Jan 2019 23:00:06 +0100 |
parents | |
children | f01eb1aed348 |
comparison
equal
deleted
inserted
replaced
15453:cdee6e827112 | 15454:1d2b5c016f17 |
---|---|
1 /* vi:set ts=8 sts=4 sw=4 noet: | |
2 * | |
3 * VIM - Vi IMproved by Bram Moolenaar | |
4 * | |
5 * Do ":help uganda" in Vim to read copying and usage conditions. | |
6 * Do ":help credits" in Vim to see a list of people who contributed. | |
7 * See README.txt for an overview of the Vim source code. | |
8 */ | |
9 | |
10 /* | |
11 * blob.c: Blob support by Yasuhiro Matsumoto | |
12 */ | |
13 | |
14 #include "vim.h" | |
15 | |
16 #if defined(FEAT_EVAL) || defined(PROTO) | |
17 | |
18 /* | |
19 * Allocate an empty blob. | |
20 * Caller should take care of the reference count. | |
21 */ | |
22 blob_T * | |
23 blob_alloc(void) | |
24 { | |
25 blob_T *blob = (blob_T *)alloc_clear(sizeof(blob_T)); | |
26 | |
27 if (blob != NULL) | |
28 ga_init2(&blob->bv_ga, 1, 100); | |
29 return blob; | |
30 } | |
31 | |
32 /* | |
33 * Allocate an empty blob for a return value, with reference count set. | |
34 * Returns OK or FAIL. | |
35 */ | |
36 int | |
37 rettv_blob_alloc(typval_T *rettv) | |
38 { | |
39 blob_T *b = blob_alloc(); | |
40 | |
41 if (b == NULL) | |
42 return FAIL; | |
43 | |
44 rettv_blob_set(rettv, b); | |
45 return OK; | |
46 } | |
47 | |
48 /* | |
49 * Set a blob as the return value. | |
50 */ | |
51 void | |
52 rettv_blob_set(typval_T *rettv, blob_T *b) | |
53 { | |
54 rettv->v_type = VAR_BLOB; | |
55 rettv->vval.v_blob = b; | |
56 if (b != NULL) | |
57 ++b->bv_refcount; | |
58 } | |
59 | |
60 void | |
61 blob_free(blob_T *b) | |
62 { | |
63 ga_clear(&b->bv_ga); | |
64 vim_free(b); | |
65 } | |
66 | |
67 /* | |
68 * Unreference a blob: decrement the reference count and free it when it | |
69 * becomes zero. | |
70 */ | |
71 void | |
72 blob_unref(blob_T *b) | |
73 { | |
74 if (b != NULL && --b->bv_refcount <= 0) | |
75 blob_free(b); | |
76 } | |
77 | |
78 /* | |
79 * Get the length of data. | |
80 */ | |
81 long | |
82 blob_len(blob_T *b) | |
83 { | |
84 if (b == NULL) | |
85 return 0L; | |
86 return b->bv_ga.ga_len; | |
87 } | |
88 | |
89 /* | |
90 * Get byte "idx" in blob "b". | |
91 * Caller must check that "idx" is valid. | |
92 */ | |
93 char_u | |
94 blob_get(blob_T *b, int idx) | |
95 { | |
96 return ((char_u*)b->bv_ga.ga_data)[idx]; | |
97 } | |
98 | |
99 /* | |
100 * Store one byte "c" in blob "b" at "idx". | |
101 * Caller must make sure that "idx" is valid. | |
102 */ | |
103 void | |
104 blob_set(blob_T *b, int idx, char_u c) | |
105 { | |
106 ((char_u*)b->bv_ga.ga_data)[idx] = c; | |
107 } | |
108 | |
109 /* | |
110 * Return TRUE when two blobs have exactly the same values. | |
111 */ | |
112 int | |
113 blob_equal( | |
114 blob_T *b1, | |
115 blob_T *b2) | |
116 { | |
117 int i; | |
118 | |
119 if (b1 == NULL || b2 == NULL) | |
120 return FALSE; | |
121 if (b1 == b2) | |
122 return TRUE; | |
123 if (blob_len(b1) != blob_len(b2)) | |
124 return FALSE; | |
125 | |
126 for (i = 0; i < b1->bv_ga.ga_len; i++) | |
127 if (blob_get(b1, i) != blob_get(b2, i)) return FALSE; | |
128 return TRUE; | |
129 } | |
130 | |
131 /* | |
132 * Read "blob" from file "fd". | |
133 * Return OK or FAIL. | |
134 */ | |
135 int | |
136 read_blob(FILE *fd, blob_T *blob) | |
137 { | |
138 struct stat st; | |
139 | |
140 if (fstat(fileno(fd), &st) < 0) | |
141 return FAIL; | |
142 if (ga_grow(&blob->bv_ga, st.st_size) == FAIL) | |
143 return FAIL; | |
144 blob->bv_ga.ga_len = st.st_size; | |
145 if (fread(blob->bv_ga.ga_data, 1, blob->bv_ga.ga_len, fd) | |
146 < (size_t)blob->bv_ga.ga_len) | |
147 return FAIL; | |
148 return OK; | |
149 } | |
150 | |
151 /* | |
152 * Write "blob" to file "fd". | |
153 * Return OK or FAIL. | |
154 */ | |
155 int | |
156 write_blob(FILE *fd, blob_T *blob) | |
157 { | |
158 if (fwrite(blob->bv_ga.ga_data, 1, blob->bv_ga.ga_len, fd) | |
159 < (size_t)blob->bv_ga.ga_len) | |
160 { | |
161 EMSG(_(e_write)); | |
162 return FAIL; | |
163 } | |
164 return OK; | |
165 } | |
166 | |
167 #endif /* defined(FEAT_EVAL) */ |