bf88b98d98d6bdc79cc8c7f7c4270d63b56819f5
[tpg/acess2.git] / Usermode / Libraries / liburi.so_src / main.c
1 /*
2  * Acess2 - URI Parser and opener
3  * By John Hodge (thePowersGang)
4  */
5 #include <acess/sys.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <ctype.h>
10 #include <uri.h>
11
12 // === STRUCTURES ===
13 struct sURIFile
14 {
15          int    Handle;
16          int    Mode;
17         tURIHandler     *Handler;
18          int    CurBlockOffset;
19         char    Buffer[];
20 };
21
22 // === PROTOTYPES ===
23  int    SoMain(void);
24 tURI    *URI_Parse(const char *String);
25 tURIFile        *URI_MakeHandle(int Mode, int Handle, tURIHandler *Handler);
26 tURIFile        *URI_Open(int Mode, tURI *URI);
27 size_t  URI_Read(tURIFile *File, size_t Bytes, void *Buffer);
28 size_t  URI_Write(tURIFile *File, size_t Bytes, void *Buffer);
29 void    URI_Close(tURIFile *File);
30 // --- file:/// handler
31  int    URI_file_Open(char *Host, int Port, char *Path, int Mode);
32 size_t  URI_file_Read(int Handle, size_t Bytes, void *Buffer);
33 size_t  URI_file_Write(int Handle, size_t Bytes, void *Buffer);
34 void    URI_file_Close(int Handle);
35 size_t  URI_file_GetSize(int Handle);
36
37 // === CONSTANTS ===
38 // Builtin URI protocol handlers
39 tURIHandler     caBuiltinHandlers[] = {
40         {"file", 0, URI_file_Open, URI_file_Close, URI_file_Read, URI_file_Write, URI_file_GetSize}
41 };
42 #define NUM_BUILTIN_HANDLERS    (sizeof(caBuiltinHandlers)/sizeof(caBuiltinHandlers[0]))
43
44 // === CODE ===
45 int SoMain(void)
46 {
47         return 0;
48 }
49
50 tURI *URI_Parse(const char *String)
51 {
52         const char      *tmp = String;
53         tURI    *ret;
54          int    protolen;
55         
56         if(!String)     return NULL;
57         
58         protolen = 0;
59         while( isalpha(*tmp) || isdigit(*tmp) ) tmp++, protolen++;
60         
61         // true URI
62         if(tmp[0] == ':' && tmp[1] == '/' && tmp[2] == '/')
63         {
64                  int    hostlen, portlen, pathlen;
65                 tmp += 3;       // Eat '://'
66                 ret = malloc(sizeof(tURI) + strlen(String) - 2);
67                 
68                 ret->Proto = (char*)ret + sizeof(tURI);
69                 memcpy(ret->Proto, String, protolen);
70                 ret->Proto[protolen] = '\0';
71                 
72                 ret->Host = ret->Proto + protolen + 1;
73                 hostlen = 0;
74                 
75                 // IPv6
76                 if( *tmp == '[' )
77                 {
78                         tmp ++;
79                         while( *tmp && *tmp != ']' ) {
80                                 ret->Host[hostlen] = *tmp;
81                                 tmp ++;
82                                 hostlen ++;
83                         }
84                         tmp ++;
85                         ret->Host[hostlen] = '\0';
86                 }
87                 // IPv4/DNS
88                 else
89                 {
90                         while( *tmp && *tmp != '/' && *tmp != ':' )
91                         {
92                                 ret->Host[hostlen] = *tmp;
93                                 tmp ++;
94                                 hostlen ++;
95                         }
96                         ret->Host[hostlen] = '\0';
97                 }
98                 
99                 // Port
100                 if( *tmp == ':' ) {
101                         ret->PortStr = ret->Host + hostlen + 1;
102                         tmp ++;
103                         portlen = 0;
104                         while(isalpha(*tmp) || isdigit(*tmp))
105                         {
106                                 ret->PortStr[portlen] = *tmp;
107                                 portlen ++;
108                                 tmp ++;
109                         }
110                         ret->PortStr[portlen] = '\0';
111                         
112                         ret->PortNum = atoi(ret->PortStr);
113                         if(!ret->PortNum && !(ret->PortStr[0] == '0' && portlen == 1) )
114                         {
115                                 // error!
116                                 ret->Path = NULL;
117                                 return ret;
118                         }
119                 }
120                 else {
121                         ret->PortStr = NULL;
122                         ret->PortNum = -1;
123                         portlen = 0;
124                 }
125                 
126                 if(*tmp == '\0')
127                 {
128                         ret->Path = NULL;
129                         return ret;
130                 }
131                 
132                 // TODO: What to do on a parse error
133                 if(*tmp != '/') {
134                         ret->Path = NULL;
135                         return ret;
136                 }
137                 
138                 if(ret->PortStr)
139                         ret->Path = ret->PortStr + portlen + 1;
140                 else
141                         ret->Path = ret->Host + hostlen + 1;
142                 
143                 tmp ++;
144                 pathlen = 0;
145                 while(*tmp)
146                 {
147                         ret->Path[pathlen] = *tmp;
148                         tmp ++;
149                         pathlen ++;
150                 }
151                 
152                 return ret;
153         }
154         else
155         {
156 //              char    *cwd;
157 //               int    retlen;
158                 
159                 // Path
160                 // TODO: What to do?
161                 // Probably return file:///<path>
162                 // but should I get the CWD and use append that?
163                 ret = malloc( sizeof(tURI) + strlen(String) + 1 );
164                 ret->Path = (char*)ret + sizeof(tURI);
165                 strcpy(ret->Path, String);
166                 ret->Proto = "file";
167                 ret->Host = NULL;
168                 ret->PortNum = 0;
169                 ret->PortStr = NULL;
170                 return ret;
171         }
172 }
173
174 tURIFile *URI_MakeHandle(int Mode, int Handle, tURIHandler *Handler)
175 {
176         tURIFile        *ret;
177         
178         ret = malloc(sizeof(tURIFile)+Handler->BlockSize);
179         if(!ret)        return NULL;
180         
181         ret->Handle = Handle;
182         ret->Mode = Mode;
183         ret->Handler = Handler;
184         ret->CurBlockOffset = 0;
185         
186         return ret;
187 }
188
189 tURIFile *URI_Open(int Mode, tURI *URI)
190 {
191         tURIHandler     *handler;
192         tURIFile        *ret;
193          int    handle;
194          int    i;
195         
196         if(!URI)
197                 return NULL;
198         
199         for( i = 0; i < NUM_BUILTIN_HANDLERS; i ++ )
200         {
201                 if(strcmp(URI->Proto, caBuiltinHandlers[i].Name) == 0)
202                         break;
203         }
204         
205         if( i == NUM_BUILTIN_HANDLERS )
206         {
207                 // TODO: Dynamics
208                 printf("URI_Open: Warning - Unknown URI handler\n");
209                 return NULL;
210         }
211         else
212                 handler = &caBuiltinHandlers[i];
213         
214         printf("URI_Open: handler->Open = %p\n", handler->Open);
215         
216         handle = handler->Open(URI->Host, URI->PortNum, URI->Path, Mode);
217         printf("URI_Open: handle = %i\n", handle);
218         if(handle == -1)        return NULL;
219         
220         printf("URI_MakeHandle(Mode=%i, handle=%i, handler=%p)\n",
221                 Mode, handle, handler);
222         ret = URI_MakeHandle(Mode, handle, handler);
223         if(!ret) {
224                 handler->Close( handle );
225                 return NULL;
226         }
227         return ret;
228 }
229
230 int URI_GetSize(tURIFile *File, size_t *Size)
231 {
232         if( !File || !Size )    return -1;
233         
234         if( File->Handler->GetSize )
235         {
236                 *Size = File->Handler->GetSize(File->Handle);
237                 return 0;       // Success
238         }
239         
240         return 1;       // Size not avaliable
241 }
242
243 /**
244  * \brief Read from a URI file
245  */
246 size_t URI_Read(tURIFile *File, size_t Bytes, void *Buffer)
247 {
248         size_t  rem = Bytes;
249         void    *buf = Buffer;
250         size_t  tmp;
251         
252         printf("URI_Read(File=%p, Bytes=%u, Buffer=%p)\n",
253                 File, (unsigned int)Bytes, Buffer);
254         
255         if(!File || !Buffer)    return -1;
256         if(Bytes == 0)  return 0;
257         
258         if( !(File->Mode & URI_MODE_READ) )     return -1;
259         
260         // Read from cache if avaliable
261         if(File->Handler->BlockSize && File->CurBlockOffset)
262         {
263                  int    avail;
264                 
265                 avail = File->Handler->BlockSize - File->CurBlockOffset;
266                 
267                 if(avail >= Bytes) {
268                         memcpy(Buffer, File->Buffer, Bytes);
269                         File->CurBlockOffset += Bytes;
270                         File->CurBlockOffset %= File->Handler->BlockSize;
271                         return Bytes;
272                 }
273                 
274                 rem -= avail;
275                 memcpy(Buffer, File->Buffer, avail);
276                 File->CurBlockOffset = 0;
277                 buf += avail;
278         }
279         
280         
281         if( File->Handler->BlockSize )
282         {
283                 // Read whole blocks
284                 while( rem >= File->Handler->BlockSize )
285                 {
286                         tmp = File->Handler->Read( File->Handle, File->Handler->BlockSize, buf );
287                         if(tmp < File->Handler->BlockSize)
288                                 return Bytes - rem - tmp;
289                         buf += File->Handler->BlockSize;
290                 }
291                 
292                 // Read the trailing part
293                 if(rem)
294                 {
295                         File->Handler->Read( File->Handle, File->Handler->BlockSize, File->Buffer );
296                         memcpy( buf, File->Buffer, rem );
297                         File->CurBlockOffset += rem;
298                 }
299                 return Bytes;
300         }
301         
302         return File->Handler->Read( File->Handle, Bytes, Buffer );
303 }
304
305 /**
306  * \brief Write to a URI file
307  */
308
309
310 // ====
311 // Builtin Handlers
312 // ====
313 int URI_file_Open(char *Host, int Port, char *Path, int Mode)
314 {
315          int    smode = 0;
316         if(Mode & URI_MODE_READ)        smode |= OPENFLAG_READ;
317         if(Mode & URI_MODE_WRITE)       smode |= OPENFLAG_WRITE;
318         
319 //      printf("URI_file_Open: open('%s', 0x%x)\n", Path, smode);
320         {
321                  int    ret;
322                 ret = open(Path, smode);
323                 return ret;
324         }
325 }
326 size_t URI_file_Read(int Handle, size_t Bytes, void *Buffer)
327 {
328 //      printf("URI_file_Read: (Handle=%i, Buffer=%p, Bytes=%i)\n",
329 //              Handle, Buffer, (int)Bytes);
330         return read(Handle, Buffer, Bytes);
331 }
332 size_t URI_file_Write(int Handle, size_t Bytes, void *Buffer)
333 {
334         return write(Handle, Buffer, Bytes);
335 }
336 void URI_file_Close(int Handle)
337 {
338         close(Handle);
339 }
340 size_t URI_file_GetSize(int Handle)
341 {
342         uint64_t curpos = tell(Handle);
343         size_t ret;
344         seek(Handle, 0, SEEK_END);
345         ret = tell(Handle);
346         seek(Handle, curpos, SEEK_SET);
347         return ret;
348 }

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