Modules/IPStack - Moving to reduction of memcpy usage
[tpg/acess2.git] / KernelLand / Modules / IPStack / buffer.c
1 /*
2  * Acess2 Networking Stack
3  * - By John Hodge (thePowersGang)
4  *
5  * buffer.c
6  * - Scatter-gather handling
7  */
8 #include "ipstack.h"
9 #include "include/buffer.h"
10
11 // === STRUCTURES ===
12 struct sIPStackBuffer
13 {
14          int    MaxSubBufffers;
15          int    nSubBuffers;
16         size_t  TotalLength;
17         struct _subbuffer
18         {
19                 const void      *Data;
20                 size_t  PreLength;
21                 size_t  PostLength;
22                 // TODO: Callbacks?
23         } SubBuffers[];
24 };
25
26 // === CODE ===
27 tIPStackBuffer *IPStack_Buffer_CreateBuffer(int MaxBuffers)
28 {
29         tIPStackBuffer *ret;
30         
31         ret = malloc( sizeof(*ret) + MaxBuffers * sizeof(ret->SubBuffers[0]) );
32         ret->MaxSubBufffers = MaxBuffers;
33         ret->nSubBuffers = 0;
34         ret->TotalLength = 0;
35         memset(ret->SubBuffers, 0, MaxBuffers * sizeof(ret->SubBuffers[0]));
36         return ret;
37 }
38
39 void IPStack_Buffer_DestroyBuffer(tIPStackBuffer *Buffer)
40 {
41         // TODO: Fire callbacks?
42         Buffer->MaxSubBufffers = 0;
43         Buffer->nSubBuffers = 0;
44         free(Buffer);
45 }
46
47 void IPStack_Buffer_AppendSubBuffer(tIPStackBuffer *Buffer,
48         size_t HeaderLen, size_t FooterLen, const void *Data,
49         tIPStackBufferCb Cb, void *Arg
50         )
51 {
52         if( Buffer->nSubBuffers == Buffer->MaxSubBufffers ) {
53                 // Ah, oops?
54                 Log_Error("IPStack", "Buffer %p only had %i sub-buffers allocated, which was not enough",
55                         Buffer, Buffer->MaxSubBufffers);
56                 return ;
57         }
58         
59         int index = Buffer->nSubBuffers++;
60         Buffer->TotalLength += HeaderLen + FooterLen;
61         
62         Buffer->SubBuffers[index].Data = Data;
63         Buffer->SubBuffers[index].PreLength = HeaderLen;
64         Buffer->SubBuffers[index].PostLength = FooterLen;
65 }
66
67 size_t IPStack_Buffer_GetLength(tIPStackBuffer *Buffer)
68 {
69         return Buffer->TotalLength;
70 }
71
72 void *IPStack_Buffer_CompactBuffer(tIPStackBuffer *Buffer, size_t *Length)
73 {
74         void    *ret;
75         ret = malloc(Buffer->TotalLength);
76         if(!ret) {
77                 *Length = 0;
78                 return NULL;
79         }
80         
81         *Length = Buffer->TotalLength;
82         
83         Uint8   *dest = ret;
84         for( int i = Buffer->nSubBuffers; i --; )
85         {
86                 memcpy(dest,
87                         Buffer->SubBuffers[i].Data,
88                         Buffer->SubBuffers[i].PreLength
89                         );
90                 dest += Buffer->SubBuffers[i].PreLength;
91         }
92         for( int i = 0; i < Buffer->nSubBuffers; i ++ )
93         {
94                 if( Buffer->SubBuffers[i].PostLength )
95                 {
96                         memcpy(dest,
97                                 (Uint8*)Buffer->SubBuffers[i].Data + Buffer->SubBuffers[i].PreLength,
98                                 Buffer->SubBuffers[i].PostLength
99                                 );
100                         dest += Buffer->SubBuffers[i].PreLength;
101                 }
102         }
103         return ret;
104 }
105
106 int IPStack_Buffer_GetBuffer(tIPStackBuffer *Buffer, int Index, size_t *Length, const void **DataPtr)
107 {
108         if( Index == -1 )       Index = 0;
109
110         if( Index >= Buffer->nSubBuffers*2 ) {
111                 return -1;
112         }
113
114         if( Index > Buffer->nSubBuffers )
115         {
116                 // Appended buffers
117                 Index -= Buffer->nSubBuffers;
118         
119                 // Bit of a hack to avoid multiple calls which return a zero length
120                 while( !Buffer->SubBuffers[Index].PostLength )
121                 {
122                         if( Index++ == Buffer->nSubBuffers )
123                                 return -1;
124                 }
125
126                 *DataPtr = (Uint8*)Buffer->SubBuffers[Index].Data + Buffer->SubBuffers[Index].PreLength;
127                 *Length = Buffer->SubBuffers[Index].PostLength;
128
129                 return (Index + 1) + Buffer->nSubBuffers;
130         }
131         else
132         {
133                 Index = Buffer->nSubBuffers - Index;
134                 // Prepended buffers
135                 *DataPtr = Buffer->SubBuffers[Index].Data;
136                 *Length = Buffer->SubBuffers[Index].PreLength;
137                 return Buffer->nSubBuffers - (Index - 1);
138         }
139 }
140

UCC git Repository :: git.ucc.asn.au