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 off_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) + protolen + 1 + strlen(tmp) + 1);
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) )
132 // TODO: What to do on a parse error
139 ret->Path = ret->PortStr + portlen + 1;
141 ret->Path = ret->Host + hostlen + 1;
144 strcpy(ret->Path, tmp);
155 // Probably return file:///<path>
156 // but should I get the CWD and use append that?
157 ret = malloc( sizeof(tURI) + strlen(String) + 1 );
158 ret->Path = (char*)ret + sizeof(tURI);
159 strcpy(ret->Path, String);
168 tURIFile *URI_MakeHandle(int Mode, int Handle, tURIHandler *Handler)
172 ret = malloc(sizeof(tURIFile)+Handler->BlockSize);
173 if(!ret) return NULL;
175 ret->Handle = Handle;
177 ret->Handler = Handler;
178 ret->CurBlockOffset = 0;
183 tURIFile *URI_Open(int Mode, tURI *URI)
185 tURIHandler *handler;
193 for( i = 0; i < NUM_BUILTIN_HANDLERS; i ++ )
195 if(strcmp(URI->Proto, caBuiltinHandlers[i].Name) == 0)
199 if( i == NUM_BUILTIN_HANDLERS )
202 printf("URI_Open: Warning - Unknown URI handler\n");
206 handler = &caBuiltinHandlers[i];
208 printf("URI_Open: handler->Open = %p\n", handler->Open);
210 handle = handler->Open(URI->Host, URI->PortNum, URI->Path, Mode);
211 printf("URI_Open: handle = %i\n", handle);
212 if(handle == -1) return NULL;
214 printf("URI_MakeHandle(Mode=%i, handle=%i, handler=%p)\n",
215 Mode, handle, handler);
216 ret = URI_MakeHandle(Mode, handle, handler);
218 handler->Close( handle );
224 int URI_GetSize(tURIFile *File, size_t *Size)
226 if( !File || !Size ) return -1;
228 if( File->Handler->GetSize )
230 *Size = File->Handler->GetSize(File->Handle);
234 return 1; // Size not avaliable
238 * \brief Read from a URI file
240 size_t URI_Read(tURIFile *File, size_t Bytes, void *Buffer)
246 printf("URI_Read(File=%p, Bytes=%u, Buffer=%p)\n",
247 File, (unsigned int)Bytes, Buffer);
249 if(!File || !Buffer) return -1;
250 if(Bytes == 0) return 0;
252 if( !(File->Mode & URI_MODE_READ) ) return -1;
254 // Read from cache if avaliable
255 if(File->Handler->BlockSize && File->CurBlockOffset)
259 avail = File->Handler->BlockSize - File->CurBlockOffset;
262 memcpy(Buffer, File->Buffer, Bytes);
263 File->CurBlockOffset += Bytes;
264 File->CurBlockOffset %= File->Handler->BlockSize;
269 memcpy(Buffer, File->Buffer, avail);
270 File->CurBlockOffset = 0;
275 if( File->Handler->BlockSize )
278 while( rem >= File->Handler->BlockSize )
280 tmp = File->Handler->Read( File->Handle, File->Handler->BlockSize, buf );
281 if(tmp < File->Handler->BlockSize)
282 return Bytes - rem - tmp;
283 buf += File->Handler->BlockSize;
286 // Read the trailing part
289 File->Handler->Read( File->Handle, File->Handler->BlockSize, File->Buffer );
290 memcpy( buf, File->Buffer, rem );
291 File->CurBlockOffset += rem;
296 return File->Handler->Read( File->Handle, Bytes, Buffer );
300 * \brief Write to a URI file
307 int URI_file_Open(char *Host, int Port, char *Path, int Mode)
310 if(Mode & URI_MODE_READ) smode |= OPENFLAG_READ;
311 if(Mode & URI_MODE_WRITE) smode |= OPENFLAG_WRITE;
313 // printf("URI_file_Open: open('%s', 0x%x)\n", Path, smode);
316 ret = _SysOpen(Path, smode);
320 size_t URI_file_Read(int Handle, size_t Bytes, void *Buffer)
322 // printf("URI_file_Read: (Handle=%i, Buffer=%p, Bytes=%i)\n",
323 // Handle, Buffer, (int)Bytes);
324 return _SysRead(Handle, Buffer, Bytes);
326 size_t URI_file_Write(int Handle, size_t Bytes, void *Buffer)
328 return _SysWrite(Handle, Buffer, Bytes);
330 void URI_file_Close(int Handle)
334 off_t URI_file_GetSize(int Handle)
336 uint64_t curpos = _SysTell(Handle);
338 _SysSeek(Handle, 0, SEEK_END);
339 ret = _SysTell(Handle);
340 _SysSeek(Handle, curpos, SEEK_SET);