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;
147 strcpy(ret->Path, tmp);
158 // Probably return file:///<path>
159 // but should I get the CWD and use append that?
160 ret = malloc( sizeof(tURI) + strlen(String) + 1 );
161 ret->Path = (char*)ret + sizeof(tURI);
162 strcpy(ret->Path, String);
171 tURIFile *URI_MakeHandle(int Mode, void *Handle, tURIHandler *Handler)
175 ret = malloc(sizeof(tURIFile)+Handler->BlockSize);
176 if(!ret) return NULL;
178 ret->Handle = Handle;
180 ret->Handler = Handler;
181 ret->CurBlockOffset = 0;
186 tURIFile *URI_Open(int Mode, tURI *URI)
188 tURIHandler *handler;
196 for( i = 0; i < NUM_BUILTIN_HANDLERS; i ++ )
198 if(strcmp(URI->Proto, caBuiltinHandlers[i].Name) == 0)
202 if( i == NUM_BUILTIN_HANDLERS )
205 printf("URI_Open: Warning - Unknown URI handler\n");
209 handler = &caBuiltinHandlers[i];
211 printf("URI_Open: handler->Open = %p\n", handler->Open);
213 handle = handler->Open(URI->Host, URI->PortNum, URI->Path, Mode);
214 printf("URI_Open: handle = %i\n", handle);
215 if(handle == NULL) return NULL;
217 printf("URI_MakeHandle(Mode=%i, handle=%i, handler=%p)\n",
218 Mode, handle, handler);
219 ret = URI_MakeHandle(Mode, handle, handler);
221 handler->Close( handle );
227 int URI_GetSize(tURIFile *File, size_t *Size)
229 if( !File || !Size ) return -1;
231 if( File->Handler->GetSize )
233 *Size = File->Handler->GetSize(File->Handle);
237 return 1; // Size not avaliable
241 * \brief Read from a URI file
243 size_t URI_Read(tURIFile *File, size_t Bytes, void *Buffer)
249 printf("URI_Read(File=%p, Bytes=%u, Buffer=%p)\n",
250 File, (unsigned int)Bytes, Buffer);
252 if(!File || !Buffer) return -1;
253 if(Bytes == 0) return 0;
255 if( !(File->Mode & URI_MODE_READ) ) return -1;
257 // Read from cache if avaliable
258 if(File->Handler->BlockSize && File->CurBlockOffset)
262 avail = File->Handler->BlockSize - File->CurBlockOffset;
265 memcpy(Buffer, File->Buffer, Bytes);
266 File->CurBlockOffset += Bytes;
267 File->CurBlockOffset %= File->Handler->BlockSize;
272 memcpy(Buffer, File->Buffer, avail);
273 File->CurBlockOffset = 0;
278 if( File->Handler->BlockSize )
281 while( rem >= File->Handler->BlockSize )
283 tmp = File->Handler->Read( File->Handle, File->Handler->BlockSize, buf );
284 if(tmp < File->Handler->BlockSize)
285 return Bytes - rem - tmp;
286 buf += File->Handler->BlockSize;
289 // Read the trailing part
292 File->Handler->Read( File->Handle, File->Handler->BlockSize, File->Buffer );
293 memcpy( buf, File->Buffer, rem );
294 File->CurBlockOffset += rem;
299 return File->Handler->Read( File->Handle, Bytes, Buffer );
303 * \brief Write to a URI file
310 void *URI_file_Open(const char *Host, int Port, const char *Path, int Mode)
312 const char *smode = NULL;
313 if( (Mode & URI_MODE_READ) && (Mode & URI_MODE_WRITE))
315 else if( (Mode & URI_MODE_READ) )
317 else if( (Mode & URI_MODE_WRITE) )
322 // printf("URI_file_Open: open('%s', 0x%x)\n", Path, smode);
323 return fopen(Path, smode);
325 size_t URI_file_Read(void *Handle, size_t Bytes, void *Buffer)
327 // printf("URI_file_Read: (Handle=%i, Buffer=%p, Bytes=%i)\n",
328 // Handle, Buffer, (int)Bytes);
329 return fread(Buffer, Bytes, 1, Handle);
331 size_t URI_file_Write(void *Handle, size_t Bytes, const void *Buffer)
333 return fwrite(Buffer, Bytes, 1, Handle);
335 void URI_file_Close(void *Handle)
339 off_t URI_file_GetSize(void *Handle)
341 off_t curpos = ftell(Handle);
343 fseek(Handle, 0, SEEK_END);
345 fseek(Handle, curpos, SEEK_SET);