3 * \author John Hodge (thePowersGang)
10 #include <udi_internal.h>
12 typedef struct sUDI_BufTag
14 struct sUDI_BufTag *Next;
16 struct sUDI_BufSect *Sect;
19 typedef struct sUDI_BufSect
21 struct sUDI_BufSect *Next;
33 tUDI_BufSect *Sections;
38 EXPORT(udi_buf_write);
44 udi_buf_copy_call_t *callback,
52 udi_buf_path_t path_handle
58 tUDI_BufSect *UDI_int_BufAddSect(size_t data_len, size_t relofs, tUDI_BufSect **prevptr, const void *data,
59 udi_buf_path_t path_handle
62 const int space_atom = 1<<7;
63 size_t space = (data_len + space_atom-1) & ~(space_atom-1);
64 tUDI_BufSect *newsect = NEW(tUDI_BufSect, + space);
65 newsect->RelOfs = relofs;
66 newsect->Length = data_len;
67 newsect->Space = space_atom;
68 newsect->Data = newsect+1;
69 memcpy(newsect->Data, data, data_len);
71 newsect->Next = *prevptr;
73 LOG("@0x%x : %p <= %p+%i", relofs, newsect->Data, data, data_len);
78 udi_buf_t *_udi_buf_allocate(const void *data, udi_size_t length, udi_buf_path_t path_handle)
80 tUDI_BufInt *buf = NEW(tUDI_BufInt,);
81 udi_buf_t *ret = &buf->buf;
84 UDI_int_BufAddSect(length, 0, &buf->Sections, data, path_handle);
86 ret->buf_size = length;
92 * \brief Write to a buffer
93 * \param callback Function to call once the write has completed
94 * \param gcb Control Block
95 * \param src_mem Source Data
96 * \param src_len Length of source data
97 * \param dst_buf Destination buffer
98 * \param dst_off Destination offset in the buffer
99 * \param dst_len Length of area to be replaced
100 * \param path_handle ???
103 udi_buf_write_call_t *callback,
110 udi_buf_path_t path_handle
113 tUDI_BufInt *dst = (void*)dst_buf;
115 dst = NEW(tUDI_BufInt,);
119 tUDI_BufSect **prevptr = &dst->Sections;
120 tUDI_BufSect *sect = dst->Sections;
121 for( ; sect; prevptr = §->Next, sect = sect->Next )
123 if(sect->RelOfs >= dst_off)
125 if(sect->RelOfs + sect->Length > dst_off)
127 dst_off -= sect->RelOfs + sect->Length;
130 // Find dst_off segment (or create one if src_len>0)
132 // or (if src_len==0) delete dst_len bytes
135 // Insert / Initialise
138 if( !sect || sect->RelOfs > dst_off ) {
139 // Simple: Just add a new section
140 UDI_int_BufAddSect(src_len, dst_off, prevptr, src_mem, path_handle);
141 dst_buf->buf_size += src_len;
143 else if( sect->RelOfs + sect->Length == dst_off ) {
144 // End of block inserts
145 size_t avail = sect->Space - sect->Length;
147 size_t bytes = MIN(avail, src_len);
148 memcpy(sect->Data + sect->Length, src_mem, bytes);
154 UDI_int_BufAddSect(src_len, 0, prevptr, src_mem, path_handle);
156 dst_buf->buf_size += src_len;
159 // Complex: Need to handle mid-section inserts
160 Log_Warning("UDI", "TODO: udi_buf_write - mid-section inserts");
173 Log_Warning("UDI", "TODO: udi_buf_write - delete");
178 Log_Warning("UDI", "TODO: udi_buf_write - overwrite");
182 callback(gcb, &dst->buf);
191 ENTER("psrc_buf isrc_off isrc_len pdst_mem",
192 src_buf, src_off, src_len, dst_mem);
193 tUDI_BufInt *src = (void*)src_buf;
195 tUDI_BufSect *sect = src->Sections;
198 for( ; sect; sect = sect->Next )
200 LOG("%x <= %x <= +%x", sect->RelOfs, src_off, sect->Length);
201 if(sect->RelOfs >= src_off)
203 if(sect->RelOfs + sect->Length > src_off)
205 src_off -= sect->RelOfs + sect->Length;
211 if( src_off < sect->RelOfs ) {
212 size_t undef_len = MIN(src_len, sect->RelOfs - src_off);
213 LOG("%i undef", undef_len);
214 memset(dst_mem, 0xFF, undef_len);
215 dst_mem += undef_len;
216 src_len -= undef_len;
217 src_off += undef_len;
221 ASSERTC(src_off, >=, sect->RelOfs);
222 size_t ofs = src_off - sect->RelOfs;
223 size_t len = MIN(src_len, sect->Length - ofs);
224 LOG("%i data from %p + %i", len, sect->Data, ofs);
225 memcpy(dst_mem, sect->Data+ofs, len);
229 src_off -= sect->RelOfs + sect->Length;
235 void udi_buf_free(udi_buf_t *buf)