#include "utils.h"

#include <errno.h>
#include <string.h>
#include <stdlib.h>

int zvfs_calc_io_units(uint64_t offset_bytes,
                       size_t   len_bytes,
                       uint32_t io_unit_size,
                       uint64_t *unit_offset,
                       uint64_t *unit_len,
                       uint32_t *buf_offset_out) {
    if (!unit_offset || !unit_len || !buf_offset_out || io_unit_size == 0) {
        return -EINVAL;
    }
    if (len_bytes == 0) {
        *unit_offset    = 0;
        *unit_len       = 0;
        *buf_offset_out = 0;
        return 0;
    }

    // offset 向下对齐到 io_unit 边界
    uint64_t aligned_offset = (offset_bytes / io_unit_size) * io_unit_size;

    // 末尾向上对齐，保证覆盖完整的请求区间
    uint64_t end_bytes   = offset_bytes + (uint64_t)len_bytes;
    uint64_t aligned_end = ((end_bytes + io_unit_size - 1) / io_unit_size) * io_unit_size;

    *unit_offset    = aligned_offset / io_unit_size;
    *unit_len       = (aligned_end - aligned_offset) / io_unit_size;
    *buf_offset_out = (uint32_t)(offset_bytes - aligned_offset);  // 原始数据在 dma_buf 内的起始偏移

    return 0;
}

int zvfs_calc_ceil_units(uint64_t bytes,
                         uint64_t unit_size,
                         uint64_t *units_out) {
    if (!units_out || unit_size == 0) {
        return -EINVAL;
    }

    *units_out = bytes / unit_size;
    if ((bytes % unit_size) != 0) {
        if (*units_out == UINT64_MAX) {
            return -EOVERFLOW;
        }
        (*units_out)++;
    }
    return 0;
}
