2019-01-12 22:47:31 +01:00
|
|
|
/* vi:set ts=8 sts=4 sw=4 noet:
|
|
|
|
*
|
|
|
|
* VIM - Vi IMproved by Bram Moolenaar
|
|
|
|
*
|
|
|
|
* Do ":help uganda" in Vim to read copying and usage conditions.
|
|
|
|
* Do ":help credits" in Vim to see a list of people who contributed.
|
|
|
|
* See README.txt for an overview of the Vim source code.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* blob.c: Blob support by Yasuhiro Matsumoto
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "vim.h"
|
|
|
|
|
|
|
|
#if defined(FEAT_EVAL) || defined(PROTO)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Allocate an empty blob.
|
|
|
|
* Caller should take care of the reference count.
|
|
|
|
*/
|
|
|
|
blob_T *
|
|
|
|
blob_alloc(void)
|
|
|
|
{
|
|
|
|
blob_T *blob = (blob_T *)alloc_clear(sizeof(blob_T));
|
|
|
|
|
|
|
|
if (blob != NULL)
|
|
|
|
ga_init2(&blob->bv_ga, 1, 100);
|
|
|
|
return blob;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Allocate an empty blob for a return value, with reference count set.
|
|
|
|
* Returns OK or FAIL.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
rettv_blob_alloc(typval_T *rettv)
|
|
|
|
{
|
|
|
|
blob_T *b = blob_alloc();
|
|
|
|
|
|
|
|
if (b == NULL)
|
|
|
|
return FAIL;
|
|
|
|
|
|
|
|
rettv_blob_set(rettv, b);
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set a blob as the return value.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
rettv_blob_set(typval_T *rettv, blob_T *b)
|
|
|
|
{
|
|
|
|
rettv->v_type = VAR_BLOB;
|
|
|
|
rettv->vval.v_blob = b;
|
|
|
|
if (b != NULL)
|
|
|
|
++b->bv_refcount;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
blob_free(blob_T *b)
|
|
|
|
{
|
|
|
|
ga_clear(&b->bv_ga);
|
|
|
|
vim_free(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Unreference a blob: decrement the reference count and free it when it
|
|
|
|
* becomes zero.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
blob_unref(blob_T *b)
|
|
|
|
{
|
|
|
|
if (b != NULL && --b->bv_refcount <= 0)
|
|
|
|
blob_free(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the length of data.
|
|
|
|
*/
|
|
|
|
long
|
|
|
|
blob_len(blob_T *b)
|
|
|
|
{
|
|
|
|
if (b == NULL)
|
|
|
|
return 0L;
|
|
|
|
return b->bv_ga.ga_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get byte "idx" in blob "b".
|
|
|
|
* Caller must check that "idx" is valid.
|
|
|
|
*/
|
|
|
|
char_u
|
|
|
|
blob_get(blob_T *b, int idx)
|
|
|
|
{
|
|
|
|
return ((char_u*)b->bv_ga.ga_data)[idx];
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Store one byte "c" in blob "b" at "idx".
|
|
|
|
* Caller must make sure that "idx" is valid.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
blob_set(blob_T *b, int idx, char_u c)
|
|
|
|
{
|
|
|
|
((char_u*)b->bv_ga.ga_data)[idx] = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return TRUE when two blobs have exactly the same values.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
blob_equal(
|
|
|
|
blob_T *b1,
|
|
|
|
blob_T *b2)
|
|
|
|
{
|
2019-01-13 15:16:13 +01:00
|
|
|
int i;
|
|
|
|
int len1 = blob_len(b1);
|
|
|
|
int len2 = blob_len(b2);
|
2019-01-12 22:47:31 +01:00
|
|
|
|
2019-01-13 15:16:13 +01:00
|
|
|
// empty and NULL are considered the same
|
|
|
|
if (len1 == 0 && len2 == 0)
|
|
|
|
return TRUE;
|
2019-01-12 22:47:31 +01:00
|
|
|
if (b1 == b2)
|
|
|
|
return TRUE;
|
2019-01-13 15:16:13 +01:00
|
|
|
if (len1 != len2)
|
2019-01-12 22:47:31 +01:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
for (i = 0; i < b1->bv_ga.ga_len; i++)
|
|
|
|
if (blob_get(b1, i) != blob_get(b2, i)) return FALSE;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read "blob" from file "fd".
|
|
|
|
* Return OK or FAIL.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
read_blob(FILE *fd, blob_T *blob)
|
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
if (fstat(fileno(fd), &st) < 0)
|
|
|
|
return FAIL;
|
|
|
|
if (ga_grow(&blob->bv_ga, st.st_size) == FAIL)
|
|
|
|
return FAIL;
|
|
|
|
blob->bv_ga.ga_len = st.st_size;
|
|
|
|
if (fread(blob->bv_ga.ga_data, 1, blob->bv_ga.ga_len, fd)
|
|
|
|
< (size_t)blob->bv_ga.ga_len)
|
|
|
|
return FAIL;
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Write "blob" to file "fd".
|
|
|
|
* Return OK or FAIL.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
write_blob(FILE *fd, blob_T *blob)
|
|
|
|
{
|
|
|
|
if (fwrite(blob->bv_ga.ga_data, 1, blob->bv_ga.ga_len, fd)
|
|
|
|
< (size_t)blob->bv_ga.ga_len)
|
|
|
|
{
|
|
|
|
EMSG(_(e_write));
|
|
|
|
return FAIL;
|
|
|
|
}
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* defined(FEAT_EVAL) */
|