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) */