vim-patch:8.1.0735: cannot handle binary data

Problem:    Cannot handle binary data.
Solution:   Add the Blob type. (Yasuhiro Matsumoto, closes vim/vim#3638)
6e5ea8d2a9

Nvim-specific Blob conversions are implemented in future commits.

Refactor write_blob() to use a FileDescriptor, as f_writefile() was
refactored to use one (does not apply to read_blob()).

Use var_check_lock() in f_add() for Blobs from v8.1.0897.

Add a modeline to test_blob.vim and fix some doc typos.

Include if_perl.txt's VIM::Blob() documentation. Interestingly, this
function already worked before this port, as it just returns a Blob
string literal, not an actual Blob object.

N/A patches for version.c:

vim-patch:8.1.0741: viminfo with Blob is not tested

Problem:    Viminfo with Blob is not tested.
Solution:   Extend the viminfo test.  Fix reading a blob.  Fixed storing a
            special variable value.
8c8b8bb56c

vim-patch:8.1.1022: may use NULL pointer when out of memory

Problem:    May use NULL pointer when out of memory. (Coverity)
Solution:   Check for blob_alloc() returning NULL.
e142a9467a
This commit is contained in:
Sean Dewar
2020-11-18 03:11:00 +00:00
parent 685cf39813
commit 9095101743
18 changed files with 1029 additions and 105 deletions

View File

@@ -64,6 +64,7 @@ enum ListLenSpecials {
typedef struct listvar_S list_T;
typedef struct dictvar_S dict_T;
typedef struct partial_S partial_T;
typedef struct blobvar_S blob_T;
typedef struct ufunc ufunc_T;
@@ -123,6 +124,7 @@ typedef enum {
VAR_SPECIAL, ///< Special value (null), .v_special
///< is used.
VAR_PARTIAL, ///< Partial, .v_partial is used.
VAR_BLOB, ///< Blob, .v_blob is used.
} VarType;
/// Structure that holds an internal variable value
@@ -138,6 +140,7 @@ typedef struct {
list_T *v_list; ///< List for VAR_LIST, can be NULL.
dict_T *v_dict; ///< Dictionary for VAR_DICT, can be NULL.
partial_T *v_partial; ///< Closure: function with args.
blob_T *v_blob; ///< Blob for VAR_BLOB, can be NULL.
} vval; ///< Actual value.
} typval_T;
@@ -252,6 +255,13 @@ struct dictvar_S {
LuaRef lua_table_ref;
};
/// Structure to hold info about a Blob
struct blobvar_S {
garray_T bv_ga; ///< Growarray with the data.
int bv_refcount; ///< Reference count.
VarLockStatus bv_lock; ///< VAR_UNLOCKED, VAR_LOCKED, VAR_FIXED.
};
/// Type used for script ID
typedef int scid_T;
/// Format argument for scid_T
@@ -711,6 +721,65 @@ static inline bool tv_dict_is_watched(const dict_T *const d)
return d && !QUEUE_EMPTY(&d->watchers);
}
static inline void tv_blob_set_ret(typval_T *const tv, blob_T *const b)
REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ARG(1);
/// Set a blob as the return value.
///
/// Increments the reference count.
///
/// @param[out] tv Object to receive the blob.
/// @param[in,out] b Blob to pass to the object.
static inline void tv_blob_set_ret(typval_T *const tv, blob_T *const b)
{
tv->v_type = VAR_BLOB;
tv->vval.v_blob = b;
if (b != NULL) {
b->bv_refcount++;
}
}
static inline int tv_blob_len(const blob_T *const b)
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
/// Get the length of the data in the blob, in bytes.
///
/// @param[in] b Blob to check.
static inline int tv_blob_len(const blob_T *const b)
{
if (b == NULL) {
return 0;
}
return b->bv_ga.ga_len;
}
static inline char_u tv_blob_get(const blob_T *const b, int idx)
REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT;
/// Get the byte at index `idx` in the blob.
///
/// @param[in] b Blob to index. Cannot be NULL.
/// @param[in] idx Index in a blob. Must be valid.
///
/// @return Byte value at the given index.
static inline char_u tv_blob_get(const blob_T *const b, int idx)
{
return ((char_u *)b->bv_ga.ga_data)[idx];
}
static inline void tv_blob_set(blob_T *const b, int idx, char_u c)
REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL;
/// Store the byte `c` at index `idx` in the blob.
///
/// @param[in] b Blob to index. Cannot be NULL.
/// @param[in] idx Index in a blob. Must be valid.
/// @param[in] c Value to store.
static inline void tv_blob_set(blob_T *const b, int idx, char_u c)
{
((char_u *)b->bv_ga.ga_data)[idx] = c;
}
/// Initialize VimL object
///
/// Initializes to unlocked VAR_UNKNOWN object.