2 * Acess2 - URI Parser and opener
3 * By John Hodge (thePowersGang)
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);
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}
42 #define NUM_BUILTIN_HANDLERS (sizeof(caBuiltinHandlers)/sizeof(caBuiltinHandlers[0]))
50 tURI *URI_Parse(const char *String)
52 const char *tmp = String;
56 if(!String) return NULL;
59 while( isalpha(*tmp) || isdigit(*tmp) ) tmp++, protolen++;
62 if(tmp[0] == ':' && tmp[1] == '/' && tmp[2] == '/')
64 int hostlen, portlen, pathlen;
65 tmp += 3; // Eat '://'
66 ret = malloc(sizeof(tURI) + strlen(String) - 2);
68 ret->Proto = (char*)ret + sizeof(tURI);
69 memcpy(ret->Proto, String, protolen);
70 ret->Proto[protolen] = '\0';
72 ret->Host = ret->Proto + protolen + 1;
79 while( *tmp && *tmp != ']' ) {
80 ret->Host[hostlen] = *tmp;
85 ret->Host[hostlen] = '\0';
90 while( *tmp && *tmp != '/' && *tmp != ':' )
92 ret->Host[hostlen] = *tmp;
96 ret->Host[hostlen] = '\0';
101 ret->PortStr = ret->Host + hostlen + 1;
104 while(isalpha(*tmp) || isdigit(*tmp))
106 ret->PortStr[portlen] = *tmp;
110 ret->PortStr[portlen] = '\0';
112 ret->PortNum = atoi(ret->PortStr);
113 if(!ret->PortNum && !(ret->PortStr[0] == '0' && portlen == 1) )
131 // TODO: What to do on a parse error
138 ret->Path = ret->PortStr + portlen + 1;
140 ret->Path = ret->Host + hostlen + 1;
146 ret->Path[pathlen] = *tmp;
160 // Probably return file:///<path>
161 // but should I get the CWD and use append that?
162 ret = malloc( sizeof(tURI) + strlen(String) + 1 );
163 ret->Path = (char*)ret + sizeof(tURI);
164 strcpy(ret->Path, String);
173 tURIFile *URI_MakeHandle(int Mode, int Handle, tURIHandler *Handler)
177 ret = malloc(sizeof(tURIFile)+Handler->BlockSize);
178 if(!ret) return NULL;
180 ret->Handle = Handle;
182 ret->Handler = Handler;
183 ret->CurBlockOffset = 0;
188 tURIFile *URI_Open(int Mode, tURI *URI)
190 tURIHandler *handler;
198 for( i = 0; i < NUM_BUILTIN_HANDLERS; i ++ )
200 if(strcmp(URI->Proto, caBuiltinHandlers[i].Name) == 0)
204 if( i == NUM_BUILTIN_HANDLERS )
207 printf("URI_Open: Warning - Unknown URI handler\n");
211 handler = &caBuiltinHandlers[i];
213 printf("URI_Open: handler->Open = %p\n", handler->Open);
215 handle = handler->Open(URI->Host, URI->PortNum, URI->Path, Mode);
216 printf("URI_Open: handle = %i\n", handle);
217 if(handle == -1) return NULL;
219 printf("URI_MakeHandle(Mode=%i, handle=%i, handler=%p)\n",
220 Mode, handle, handler);
221 ret = URI_MakeHandle(Mode, handle, handler);
223 handler->Close( handle );
229 int URI_GetSize(tURIFile *File, size_t *Size)
231 if( !File || !Size ) return -1;
233 if( File->Handler->GetSize )
235 *Size = File->Handler->GetSize(File->Handle);
239 return 1; // Size not avaliable
243 * \brief Read from a URI file
245 size_t URI_Read(tURIFile *File, size_t Bytes, void *Buffer)
251 printf("URI_Read(File=%p, Bytes=%u, Buffer=%p)\n",
252 File, Bytes, Buffer);
254 if(!File || !Buffer) return -1;
255 if(Bytes == 0) return 0;
257 if( !(File->Mode & URI_MODE_READ) ) return -1;
259 // Read from cache if avaliable
260 if(File->Handler->BlockSize && File->CurBlockOffset)
264 avail = File->Handler->BlockSize - File->CurBlockOffset;
267 memcpy(Buffer, File->Buffer, Bytes);
268 File->CurBlockOffset += Bytes;
269 File->CurBlockOffset %= File->Handler->BlockSize;
274 memcpy(Buffer, File->Buffer, avail);
275 File->CurBlockOffset = 0;
280 if( File->Handler->BlockSize )
283 while( rem >= File->Handler->BlockSize )
285 tmp = File->Handler->Read( File->Handle, File->Handler->BlockSize, buf );
286 if(tmp < File->Handler->BlockSize)
287 return Bytes - rem - tmp;
288 buf += File->Handler->BlockSize;
291 // Read the trailing part
294 File->Handler->Read( File->Handle, File->Handler->BlockSize, File->Buffer );
295 memcpy( buf, File->Buffer, rem );
296 File->CurBlockOffset += rem;
301 return File->Handler->Read( File->Handle, Bytes, Buffer );
305 * \brief Write to a URI file
312 int URI_file_Open(char *Host, int Port, char *Path, int Mode)
315 if(Mode & URI_MODE_READ) smode |= OPENFLAG_READ;
316 if(Mode & URI_MODE_WRITE) smode |= OPENFLAG_WRITE;
318 printf("URI_file_Open: open('%s', 0x%x)\n", Path, smode);
321 ret = open(Path, smode);
325 size_t URI_file_Read(int Handle, size_t Bytes, void *Buffer)
327 printf("URI_file_Read: (Handle=%i, Buffer=%p, Bytes=%i)\n",
328 Handle, Buffer, Bytes);
329 return read(Handle, Buffer, Bytes);
331 size_t URI_file_Write(int Handle, size_t Bytes, void *Buffer)
333 return write(Handle, Buffer, Bytes);
335 void URI_file_Close(int Handle)
339 size_t URI_file_GetSize(int Handle)
341 uint64_t curpos = tell(Handle);
343 seek(Handle, 0, SEEK_END);
345 seek(Handle, curpos, SEEK_SET);