Mercurial > hg > th-libs
comparison th_ioctx_mem.c @ 678:7e207f1023d9
Split stdio and memio stuff to separate files from th_stdio.c
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sat, 29 Feb 2020 12:19:02 +0200 |
parents | |
children | 81d1a3f53b87 |
comparison
equal
deleted
inserted
replaced
677:927772fb0745 | 678:7e207f1023d9 |
---|---|
1 /* | |
2 * Simple I/O abstraction and context handling layer | |
3 * Programmed and designed by Matti 'ccr' Hamalainen | |
4 * (C) Copyright 2012-2020 Tecnic Software productions (TNSP) | |
5 * | |
6 * Please read file 'COPYING' for information on license and distribution. | |
7 */ | |
8 #include "th_ioctx.h" | |
9 | |
10 | |
11 static BOOL th_mem_realloc(th_ioctx *ctx, const size_t newSize) | |
12 { | |
13 size_t grow; | |
14 | |
15 if (ctx->maxSize > 0 && newSize > ctx->maxSize) | |
16 { | |
17 ctx->status = THERR_BOUNDS; | |
18 return FALSE; | |
19 } | |
20 | |
21 if (newSize < ctx->memAlloc) | |
22 return TRUE; | |
23 | |
24 grow = (ctx->minAlloc > 0) ? ctx->minAlloc : 8 * 1024; | |
25 if (newSize - ctx->memAlloc > grow) | |
26 grow += newSize - ctx->memAlloc; | |
27 | |
28 if (ctx->maxSize > 0 && ctx->memAlloc + grow >= ctx->maxSize) | |
29 { | |
30 ctx->status = THERR_BOUNDS; | |
31 return FALSE; | |
32 } | |
33 | |
34 ctx->memAlloc += grow; | |
35 if ((ctx->memData = th_realloc(ctx->memData, ctx->memAlloc)) == NULL) | |
36 { | |
37 ctx->status = THERR_MALLOC; | |
38 return FALSE; | |
39 } | |
40 | |
41 ctx->memSize = newSize; | |
42 | |
43 return TRUE; | |
44 } | |
45 | |
46 | |
47 static int th_mem_freset(th_ioctx *ctx) | |
48 { | |
49 ctx->memOffset = 0; | |
50 return THERR_OK; | |
51 } | |
52 | |
53 | |
54 static int th_mem_ferror(th_ioctx *ctx) | |
55 { | |
56 return ctx->status; | |
57 } | |
58 | |
59 | |
60 static int th_mem_fseek(th_ioctx *ctx, const off_t offset, const int whence) | |
61 { | |
62 off_t newPos; | |
63 | |
64 // Calculate the new position | |
65 switch (whence) | |
66 { | |
67 case SEEK_SET: | |
68 newPos = offset; | |
69 break; | |
70 | |
71 case SEEK_CUR: | |
72 newPos = ctx->memOffset + offset; | |
73 break; | |
74 | |
75 case SEEK_END: | |
76 newPos = ctx->memSize + offset; | |
77 break; | |
78 | |
79 default: | |
80 return -1; | |
81 } | |
82 | |
83 // Set the new position | |
84 ctx->memOffset = newPos; | |
85 | |
86 // Check the new position | |
87 if (newPos < 0) | |
88 return -1; | |
89 | |
90 //if (!th_mem_realloc(ctx, newPos)) | |
91 // return -1; | |
92 | |
93 return 0; | |
94 } | |
95 | |
96 | |
97 static off_t th_mem_fsize(th_ioctx *ctx) | |
98 { | |
99 return ctx->memSize; | |
100 } | |
101 | |
102 | |
103 static off_t th_mem_ftell(th_ioctx *ctx) | |
104 { | |
105 return ctx->memOffset; | |
106 } | |
107 | |
108 | |
109 static BOOL th_mem_feof(th_ioctx *ctx) | |
110 { | |
111 return ((size_t) ctx->memOffset) >= ctx->memSize; | |
112 } | |
113 | |
114 | |
115 static int th_mem_fgetc(th_ioctx *ctx) | |
116 { | |
117 // Check for EOF | |
118 if ((size_t) ctx->memOffset < ctx->memSize) | |
119 return ctx->memData[ctx->memOffset++]; | |
120 else | |
121 return EOF; | |
122 } | |
123 | |
124 | |
125 static size_t th_mem_fread(void *buf, size_t size, size_t nmemb, th_ioctx *ctx) | |
126 { | |
127 size_t length = size * nmemb; | |
128 | |
129 // Check if we can read the whole chunk | |
130 if (((size_t) ctx->memOffset + length) >= ctx->memSize) | |
131 { | |
132 nmemb = (ctx->memSize - ctx->memOffset) / size; | |
133 length = size * nmemb; | |
134 } | |
135 | |
136 memcpy(buf, ctx->memData + ctx->memOffset, length); | |
137 ctx->memOffset += length; | |
138 return nmemb; | |
139 } | |
140 | |
141 | |
142 static int th_mem_fputc(int ch, th_ioctx *ctx) | |
143 { | |
144 // Check for EOF | |
145 if (!th_mem_realloc(ctx, ctx->memOffset + 1)) | |
146 return EOF; | |
147 | |
148 ctx->memData[ctx->memOffset++] = ch; | |
149 return ch; | |
150 } | |
151 | |
152 | |
153 static size_t th_mem_fwrite(const void *buf, size_t size, size_t nmemb, th_ioctx *ctx) | |
154 { | |
155 size_t length = size * nmemb; | |
156 | |
157 // Check if we can write the whole chunk | |
158 if (!th_mem_realloc(ctx, ctx->memOffset + length)) | |
159 { | |
160 nmemb = (ctx->memSize - ctx->memOffset) / size; | |
161 length = size * nmemb; | |
162 } | |
163 | |
164 if (length > 0) | |
165 { | |
166 memcpy(ctx->memData + ctx->memOffset, buf, length); | |
167 ctx->memOffset += length; | |
168 } | |
169 return nmemb; | |
170 } | |
171 | |
172 | |
173 const th_ioctx_ops th_mem_io_ops = | |
174 { | |
175 "MemIO", | |
176 | |
177 NULL, | |
178 NULL, | |
179 | |
180 th_mem_freset, | |
181 th_mem_ferror, | |
182 th_mem_fseek, | |
183 th_mem_fsize, | |
184 th_mem_ftell, | |
185 th_mem_feof, | |
186 th_mem_fgetc, | |
187 th_mem_fputc, | |
188 th_mem_fread, | |
189 th_mem_fwrite, | |
190 | |
191 NULL, | |
192 NULL, | |
193 NULL | |
194 }; |