2 * Acess2 - URI Parser and opener
3 * By John Hodge (thePowersGang)
23 tURI *URI_Parse(const char *String);
24 tURIFile *URI_MakeHandle(int Mode, void *Handle, tURIHandler *Handler);
25 tURIFile *URI_Open(int Mode, tURI *URI);
26 size_t URI_Read(tURIFile *File, size_t Bytes, void *Buffer);
27 size_t URI_Write(tURIFile *File, size_t Bytes, void *Buffer);
28 void URI_Close(tURIFile *File);
29 // --- file:/// handler
30 void *URI_file_Open(const char *Host, int Port, const char *Path, int Mode);
31 void URI_file_Close(void *Handle);
32 size_t URI_file_Read(void *Handle, size_t Bytes, void *Buffer);
33 size_t URI_file_Write(void *Handle, size_t Bytes, const void *Buffer);
34 off_t URI_file_GetSize(void *Handle);
37 // Builtin URI protocol handlers
38 tURIHandler caBuiltinHandlers[] = {
40 URI_file_Open, URI_file_Close,
41 URI_file_Read, URI_file_Write,
45 #define NUM_BUILTIN_HANDLERS (sizeof(caBuiltinHandlers)/sizeof(caBuiltinHandlers[0]))
53 tURI *URI_Parse(const char *String)
55 const char *tmp = String;
59 if(!String) return NULL;
62 while( isalpha(*tmp) || isdigit(*tmp) ) tmp++, protolen++;
65 if(tmp[0] == ':' && tmp[1] == '/' && tmp[2] == '/')
67 int hostlen, portlen, pathlen;
68 tmp += 3; // Eat '://'
69 ret = malloc(sizeof(tURI) + protolen + 1 + strlen(tmp) + 1);
71 ret->Proto = (char*)ret + sizeof(tURI);
72 memcpy(ret->Proto, String, protolen);
73 ret->Proto[protolen] = '\0';
75 ret->Host = ret->Proto + protolen + 1;
82 while( *tmp && *tmp != ']' ) {
83 ret->Host[hostlen] = *tmp;
88 ret->Host[hostlen] = '\0';
93 while( *tmp && *tmp != '/' && *tmp != ':' )
95 ret->Host[hostlen] = *tmp;
99 ret->Host[hostlen] = '\0';
104 ret->PortStr = ret->Host + hostlen + 1;
107 while(isalpha(*tmp) || isdigit(*tmp))
109 ret->PortStr[portlen] = *tmp;
113 ret->PortStr[portlen] = '\0';
115 ret->PortNum = atoi(ret->PortStr);
116 if(!ret->PortNum && !(ret->PortStr[0] == '0' && portlen == 1) )
135 // TODO: What to do on a parse error
142 ret->Path = ret->PortStr + portlen + 1;
144 ret->Path = ret->Host + hostlen + 1;
146 strcpy(ret->Path, tmp);
157 // Probably return file:///<path>
158 // but should I get the CWD and use append that?
159 ret = malloc( sizeof(tURI) + strlen(String) + 1 );
160 ret->Path = (char*)ret + sizeof(tURI);
161 strcpy(ret->Path, String);
170 tURIFile *URI_MakeHandle(int Mode, void *Handle, tURIHandler *Handler)
174 ret = malloc(sizeof(tURIFile)+Handler->BlockSize);
175 if(!ret) return NULL;
177 ret->Handle = Handle;
179 ret->Handler = Handler;
180 ret->CurBlockOffset = 0;
185 tURIFile *URI_Open(int Mode, tURI *URI)
187 tURIHandler *handler;
195 for( i = 0; i < NUM_BUILTIN_HANDLERS; i ++ )
197 if(strcmp(URI->Proto, caBuiltinHandlers[i].Name) == 0)
201 if( i == NUM_BUILTIN_HANDLERS )
204 printf("URI_Open: Warning - Unknown URI handler\n");
208 handler = &caBuiltinHandlers[i];
210 printf("URI_Open: handler->Open = %p\n", handler->Open);
212 handle = handler->Open(URI->Host, URI->PortNum, URI->Path, Mode);
213 printf("URI_Open: handle = %i\n", handle);
214 if(handle == NULL) return NULL;
216 printf("URI_MakeHandle(Mode=%i, handle=%i, handler=%p)\n",
217 Mode, handle, handler);
218 ret = URI_MakeHandle(Mode, handle, handler);
220 handler->Close( handle );
226 int URI_GetSize(tURIFile *File, size_t *Size)
228 if( !File || !Size ) return -1;
230 if( File->Handler->GetSize )
232 *Size = File->Handler->GetSize(File->Handle);
236 return 1; // Size not avaliable
240 * \brief Read from a URI file
242 size_t URI_Read(tURIFile *File, size_t Bytes, void *Buffer)
248 printf("URI_Read(File=%p, Bytes=%u, Buffer=%p)\n",
249 File, (unsigned int)Bytes, Buffer);
251 if(!File || !Buffer) return -1;
252 if(Bytes == 0) return 0;
254 if( !(File->Mode & URI_MODE_READ) ) return -1;
256 // Read from cache if avaliable
257 if(File->Handler->BlockSize && File->CurBlockOffset)
261 avail = File->Handler->BlockSize - File->CurBlockOffset;
264 memcpy(Buffer, File->Buffer, Bytes);
265 File->CurBlockOffset += Bytes;
266 File->CurBlockOffset %= File->Handler->BlockSize;
271 memcpy(Buffer, File->Buffer, avail);
272 File->CurBlockOffset = 0;
277 if( File->Handler->BlockSize )
280 while( rem >= File->Handler->BlockSize )
282 tmp = File->Handler->Read( File->Handle, File->Handler->BlockSize, buf );
283 if(tmp < File->Handler->BlockSize)
284 return Bytes - rem - tmp;
285 buf += File->Handler->BlockSize;
288 // Read the trailing part
291 File->Handler->Read( File->Handle, File->Handler->BlockSize, File->Buffer );
292 memcpy( buf, File->Buffer, rem );
293 File->CurBlockOffset += rem;
298 return File->Handler->Read( File->Handle, Bytes, Buffer );
302 * \brief Write to a URI file
309 void *URI_file_Open(const char *Host, int Port, const char *Path, int Mode)
311 const char *smode = NULL;
312 if( (Mode & URI_MODE_READ) && (Mode & URI_MODE_WRITE))
314 else if( (Mode & URI_MODE_READ) )
316 else if( (Mode & URI_MODE_WRITE) )
321 // printf("URI_file_Open: open('%s', 0x%x)\n", Path, smode);
322 return fopen(Path, smode);
324 size_t URI_file_Read(void *Handle, size_t Bytes, void *Buffer)
326 // printf("URI_file_Read: (Handle=%i, Buffer=%p, Bytes=%i)\n",
327 // Handle, Buffer, (int)Bytes);
328 return fread(Buffer, Bytes, 1, Handle);
330 size_t URI_file_Write(void *Handle, size_t Bytes, const void *Buffer)
332 return fwrite(Buffer, Bytes, 1, Handle);
334 void URI_file_Close(void *Handle)
338 off_t URI_file_GetSize(void *Handle)
340 off_t curpos = ftell(Handle);
342 fseek(Handle, 0, SEEK_END);
344 fseek(Handle, curpos, SEEK_SET);