예제 #1
0
SOL_API int
sol_buffer_set_char_at(struct sol_buffer *buf, size_t pos, char c)
{
    int err;
    const size_t nul_size = nul_byte_size(buf);

    SOL_NULL_CHECK(buf, -EINVAL);
    if (buf->used < pos) {
        return -EINVAL;
    }

    /* Extra room for the ending NUL-byte. */
    if (1 >= SIZE_MAX - nul_size - pos)
        return -EOVERFLOW;
    err = sol_buffer_ensure(buf, pos + 1 + nul_size);
    if (err < 0)
        return err;

    *((char *)buf->data + pos) = c;

    if (pos + 1 >= buf->used)
        buf->used = pos + 1;

    if (nul_byte_size(buf))
        return sol_buffer_ensure_nul_byte(buf);

    return 0;
}
예제 #2
0
SOL_API int
sol_buffer_insert_char(struct sol_buffer *buf, size_t pos, const char c)
{
    char *p;
    size_t new_size;
    int err;

    SOL_NULL_CHECK(buf, -EINVAL);
    SOL_INT_CHECK(pos, > buf->used, -EINVAL);

    if (pos == buf->used)
        return sol_buffer_append_char(buf, c);

    err = sol_util_size_add(buf->used, 1, &new_size);
    if (err < 0)
        return err;

    err = sol_buffer_ensure(buf, new_size);
    if (err < 0)
        return err;

    p = sol_buffer_at(buf, pos);
    memmove(p + 1, p, buf->used - pos);
    *p = c;
    buf->used++;

    if (nul_byte_size(buf))
        return sol_buffer_ensure_nul_byte(buf);
    return 0;
}
예제 #3
0
SOL_API int
sol_buffer_append_char(struct sol_buffer *buf, const char c)
{
    char *p;
    size_t new_size;
    int err;

    SOL_NULL_CHECK(buf, -EINVAL);

    err = sol_util_size_add(buf->used, 1, &new_size);
    if (err < 0)
        return err;

    err = sol_buffer_ensure(buf, new_size);
    if (err < 0)
        return err;

    p = sol_buffer_at_end(buf);
    *p = c;
    buf->used++;

    if (nul_byte_size(buf))
        return sol_buffer_ensure_nul_byte(buf);
    return 0;
}
예제 #4
0
SOL_API int
sol_buffer_set_slice_at(struct sol_buffer *buf, size_t pos, const struct sol_str_slice slice)
{
    int err;
    const size_t nul_size = nul_byte_size(buf);

    SOL_NULL_CHECK(buf, -EINVAL);
    if (buf->used < pos) {
        return -EINVAL;
    }

    /* Extra room for the ending NUL-byte. */
    if (slice.len >= SIZE_MAX - nul_size - pos)
        return -EOVERFLOW;
    err = sol_buffer_ensure(buf, pos + slice.len + nul_size);
    if (err < 0)
        return err;

    /* deal with possible overlaps with memmove */
    memmove((char *)buf->data + pos, slice.data, slice.len);

    if (pos + slice.len >= buf->used) {
        buf->used = pos + slice.len;
        /* only terminate if we're growing */
        ((char *)buf->data)[buf->used] = 0;
    }

    return 0;
}
예제 #5
0
SOL_API int
sol_buffer_append_slice(struct sol_buffer *buf, const struct sol_str_slice slice)
{
    const size_t nul_size = nul_byte_size(buf);
    char *p;
    size_t new_size;
    int err;

    SOL_NULL_CHECK(buf, -EINVAL);

    err = sol_util_size_add(buf->used, slice.len, &new_size);
    if (err < 0)
        return err;

    /* Extra room for the ending NUL-byte. */
    if (new_size >= SIZE_MAX - nul_size)
        return -EOVERFLOW;
    err = sol_buffer_ensure(buf, new_size + nul_size);
    if (err < 0)
        return err;

    p = sol_buffer_at_end(buf);
    memcpy(p, slice.data, slice.len);

    if (nul_size)
        p[slice.len] = '\0';
    buf->used += slice.len;
    return 0;
}
예제 #6
0
SOL_API int
sol_buffer_ensure(struct sol_buffer *buf, size_t min_size)
{
    int err;

    SOL_NULL_CHECK(buf, -EINVAL);

    if (min_size >= SIZE_MAX - nul_byte_size(buf))
        return -EINVAL;
    if (buf->capacity >= min_size)
        return 0;

    err = sol_buffer_resize(buf, align_power2(min_size + nul_byte_size(buf)));
    if (err == -EPERM)
        return -ENOMEM;
    return err;
}
예제 #7
0
SOL_API int
sol_buffer_set_slice(struct sol_buffer *buf, const struct sol_str_slice slice)
{
    int err;

    SOL_NULL_CHECK(buf, -EINVAL);

    /* Extra room for the ending NUL-byte. */
    if (slice.len >= SIZE_MAX - nul_byte_size(buf))
        return -EOVERFLOW;
    err = sol_buffer_ensure(buf, slice.len + nul_byte_size(buf));
    if (err < 0)
        return err;

    sol_str_slice_copy(buf->data, slice);
    buf->used = slice.len;
    return 0;
}
예제 #8
0
SOL_API int
sol_buffer_insert_from_base16(struct sol_buffer *buf, size_t pos, const struct sol_str_slice slice, enum sol_decode_case decode_case)
{
    char *p;
    size_t new_size;
    ssize_t decoded_size, r;
    const size_t nul_size = nul_byte_size(buf);
    int err;

    SOL_NULL_CHECK(buf, -EINVAL);
    SOL_INT_CHECK(pos, > buf->used, -EINVAL);

    if (slice.len == 0)
        return 0;

    if (pos == buf->used)
        return sol_buffer_append_from_base16(buf, slice, decode_case);

    decoded_size = sol_util_base16_calculate_decoded_len(slice);
    if (decoded_size < 0)
        return decoded_size;

    err = sol_util_size_add(buf->used, decoded_size, &new_size);
    if (err < 0)
        return err;

    if (nul_size) {
        err = sol_util_size_add(new_size, nul_size, &new_size);
        if (err < 0)
            return err;
    }

    err = sol_buffer_ensure(buf, new_size);
    if (err < 0)
        return err;

    p = sol_buffer_at(buf, pos);
    memmove(p + decoded_size, p, buf->used - pos);
    r = sol_util_base16_decode(p, decoded_size, slice, decode_case);
    if (r != decoded_size) {
        memmove(p, p + decoded_size, buf->used - pos);
        if (nul_size)
            sol_buffer_ensure_nul_byte(buf);
        if (r < 0)
            return r;
        else
            return -EINVAL;
    }

    buf->used += decoded_size;

    if (nul_size)
        return sol_buffer_ensure_nul_byte(buf);
    return 0;
}
예제 #9
0
SOL_API int
sol_buffer_insert_as_base64(struct sol_buffer *buf, size_t pos, const struct sol_str_slice slice, const char base64_map[SOL_STATIC_ARRAY_SIZE(65)])
{
    char *p;
    size_t new_size;
    ssize_t encoded_size, r;
    const size_t nul_size = nul_byte_size(buf);
    int err;

    SOL_NULL_CHECK(buf, -EINVAL);
    SOL_INT_CHECK(pos, > buf->used, -EINVAL);

    if (slice.len == 0)
        return 0;

    if (pos == buf->used)
        return sol_buffer_append_as_base64(buf, slice, base64_map);

    encoded_size = sol_util_base64_calculate_encoded_len(slice, base64_map);
    if (encoded_size < 0)
        return encoded_size;

    err = sol_util_size_add(buf->used, encoded_size, &new_size);
    if (err < 0)
        return err;

    if (nul_size) {
        err = sol_util_size_add(new_size, nul_size, &new_size);
        if (err < 0)
            return err;
    }

    err = sol_buffer_ensure(buf, new_size);
    if (err < 0)
        return err;

    p = sol_buffer_at(buf, pos);
    memmove(p + encoded_size, p, buf->used - pos);
    r = sol_util_base64_encode(p, encoded_size, slice, base64_map);
    if (r != encoded_size) {
        memmove(p, p + encoded_size, buf->used - pos);
        if (nul_size)
            sol_buffer_ensure_nul_byte(buf);
        if (r < 0)
            return r;
        else
            return -EINVAL;
    }

    buf->used += encoded_size;

    if (nul_size)
        return sol_buffer_ensure_nul_byte(buf);
    return 0;
}
예제 #10
0
SOL_API int
sol_buffer_append_as_base16(struct sol_buffer *buf, const struct sol_str_slice slice, bool uppercase)
{
    char *p;
    size_t new_size;
    ssize_t encoded_size, r;
    const size_t nul_size = nul_byte_size(buf);
    int err;

    SOL_NULL_CHECK(buf, -EINVAL);

    if (slice.len == 0)
        return 0;

    encoded_size = sol_util_base16_calculate_encoded_len(slice);
    if (encoded_size < 0)
        return encoded_size;

    err = sol_util_size_add(buf->used, encoded_size, &new_size);
    if (err < 0)
        return err;

    if (nul_size) {
        err = sol_util_size_add(new_size, nul_size, &new_size);
        if (err < 0)
            return err;
    }

    err = sol_buffer_ensure(buf, new_size);
    if (err < 0)
        return err;

    p = sol_buffer_at_end(buf);
    r = sol_util_base16_encode(p, encoded_size, slice, uppercase);
    if (r != encoded_size) {
        if (nul_size)
            sol_buffer_ensure_nul_byte(buf);
        if (r < 0)
            return r;
        else
            return -EINVAL;
    }

    buf->used += encoded_size;

    if (nul_size)
        return sol_buffer_ensure_nul_byte(buf);
    return 0;
}
예제 #11
0
SOL_API int
sol_buffer_append_from_base64(struct sol_buffer *buf, const struct sol_str_slice slice, const char base64_map[SOL_STATIC_ARRAY_SIZE(65)])
{
    char *p;
    size_t new_size;
    ssize_t decoded_size, r;
    const size_t nul_size = nul_byte_size(buf);
    int err;

    SOL_NULL_CHECK(buf, -EINVAL);

    if (slice.len == 0)
        return 0;

    decoded_size = sol_util_base64_calculate_decoded_len(slice, base64_map);
    if (decoded_size < 0)
        return decoded_size;

    err = sol_util_size_add(buf->used, decoded_size, &new_size);
    if (err < 0)
        return err;

    if (nul_size) {
        err = sol_util_size_add(new_size, nul_size, &new_size);
        if (err < 0)
            return err;
    }

    err = sol_buffer_ensure(buf, new_size);
    if (err < 0)
        return err;

    p = sol_buffer_at_end(buf);
    r = sol_util_base64_decode(p, decoded_size, slice, base64_map);
    if (r != decoded_size) {
        if (nul_size)
            sol_buffer_ensure_nul_byte(buf);
        if (r < 0)
            return r;
        else
            return -EINVAL;
    }

    buf->used += decoded_size;

    if (nul_size)
        return sol_buffer_ensure_nul_byte(buf);
    return 0;
}
예제 #12
0
SOL_API int
sol_buffer_insert_slice(struct sol_buffer *buf, size_t pos, const struct sol_str_slice slice)
{
    const size_t nul_size = nul_byte_size(buf);
    char *p;
    size_t new_size;
    int err;

    SOL_NULL_CHECK(buf, -EINVAL);
    SOL_INT_CHECK(pos, > buf->used, -EINVAL);

    if (pos == buf->used)
        return sol_buffer_append_slice(buf, slice);

    err = sol_util_size_add(buf->used, slice.len, &new_size);
    if (err < 0)
        return err;

    /* Extra room for the ending NUL-byte. */
    if (new_size >= SIZE_MAX - nul_size)
        return -EOVERFLOW;
    err = sol_buffer_ensure(buf, new_size + nul_size);
    if (err < 0)
        return err;

    p = sol_buffer_at(buf, pos);
    memmove(p + slice.len, p, buf->used - pos);
    memcpy(p, slice.data, slice.len);
    buf->used += slice.len;

    if (nul_size) {
        p = sol_buffer_at_end(buf);
        p[0] = '\0';
    }

    return 0;
}