BeRTOS
kfile_block.c
Go to the documentation of this file.
00001 
00040 #include "kfile_block.h"
00041 #include <string.h>
00042 
00043 
00047 #define KFT_KFILEBLOCK MAKE_ID('K', 'F', 'B', 'L')
00048 
00052 INLINE KFileBlock * KFILEBLOCK_CAST(KFile *fd)
00053 {
00054     ASSERT(fd->_type == KFT_KFILEBLOCK);
00055     return (KFileBlock *)fd;
00056 }
00057 
00058 #define KFILEBLOCK(dir, fd, buf, size) \
00059 ({ \
00060     KFileBlock *fb = KFILEBLOCK_CAST(fd); \
00061     size_t len = 0; \
00062     while (size) \
00063     { \
00064         block_idx_t id = (fd)->seek_pos / fb->blk->blk_size; \
00065         if (id >= fb->blk->blk_cnt) \
00066             break; \
00067         size_t offset = (fd)->seek_pos % fb->blk->blk_size; \
00068         size_t count = MIN(size, (size_t)(fb->blk->blk_size - offset)); \
00069         size_t ret_len = kblock_##dir(fb->blk, id, buf, offset, count); \
00070         size -= ret_len; \
00071         (fd)->seek_pos += ret_len; \
00072         buf = buf + ret_len; \
00073         len += ret_len; \
00074         if (ret_len != count) \
00075             break; \
00076     } \
00077     len; \
00078 })
00079 
00080 static size_t kfileblock_read(struct KFile *fd, void *_buf, size_t size)
00081 {
00082     uint8_t *buf = (uint8_t *)_buf;
00083     return KFILEBLOCK(read, fd, buf, size);
00084 }
00085 
00086 static size_t kfileblock_write(struct KFile *fd, const void *_buf, size_t size)
00087 {
00088     const uint8_t *buf = (const uint8_t *)_buf;
00089     return KFILEBLOCK(write, fd, buf, size);
00090 }
00091 
00092 static int kfileblock_flush(struct KFile *fd)
00093 {
00094     KFileBlock *fb = KFILEBLOCK_CAST(fd);
00095     return kblock_flush(fb->blk);
00096 }
00097 
00098 static int kfileblock_error(struct KFile *fd)
00099 {
00100     KFileBlock *fb = KFILEBLOCK_CAST(fd);
00101     return kblock_error(fb->blk);
00102 }
00103 
00104 static void kfileblock_clearerr(struct KFile *fd)
00105 {
00106     KFileBlock *fb = KFILEBLOCK_CAST(fd);
00107     return kblock_clearerr(fb->blk);
00108 }
00109 
00110 static int kfileblock_close(struct KFile *fd)
00111 {
00112     KFileBlock *fb = KFILEBLOCK_CAST(fd);
00113     return kblock_close(fb->blk);
00114 }
00115 
00116 void kfileblock_init(KFileBlock *fb, KBlock *blk)
00117 {
00118     ASSERT(fb);
00119     ASSERT(blk);
00120     memset(fb, 0, sizeof(*fb));
00121     kfile_init(&fb->fd);
00122     DB(fb->fd._type = KFT_KFILEBLOCK);
00123     fb->blk = blk;
00124     fb->fd.size = blk->blk_cnt * blk->blk_size;
00125     fb->fd.read = kfileblock_read;
00126     fb->fd.write = kfileblock_write;
00127     fb->fd.flush = kfileblock_flush;
00128     fb->fd.error = kfileblock_error;
00129     fb->fd.clearerr = kfileblock_clearerr;
00130     fb->fd.close = kfileblock_close;
00131 }