1 /*
2     Copyright (C) 2000 Masanao Izumo <mo@goice.co.jp>
3 
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18 
19 #include "config.h"
20 #include <stdio.h>
21 #include <stdlib.h>
22 #ifndef NO_STRING_H
23 #include <string.h>
24 #else
25 #include <strings.h>
26 #endif
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif /* HAVE_UNISTD_H */
30 #include "libarc/url.h"
31 
32 typedef struct _URL_mem
33 {
34     char common[sizeof(struct _URL)];
35     char *memory;
36     long  memsiz;
37     long  mempos;
38     int   autofree;
39 } URL_mem;
40 
41 static long url_mem_read(URL url, void *buff, long n);
42 static char *url_mem_gets(URL url, char *buff, int n);
43 static int url_mem_fgetc(URL url);
44 static long url_mem_seek(URL url, long offset, int whence);
45 static long url_mem_tell(URL url);
46 static void url_mem_close(URL url);
47 
url_mem_open(char * memory,long memsiz,int autofree)48 URL url_mem_open(char *memory, long memsiz, int autofree)
49 {
50     URL_mem *url;
51 
52     url = (URL_mem *)alloc_url(sizeof(URL_mem));
53     if(url == NULL)
54     {
55 	url_errno = errno;
56 	if(autofree)
57 	{
58 	    free(memory);
59 	    errno = url_errno;
60 	}
61 	return NULL;
62     }
63 
64     /* common members */
65     URLm(url, type)      = URL_mem_t;
66     URLm(url, url_read)  = url_mem_read;
67     URLm(url, url_gets)  = url_mem_gets;
68     URLm(url, url_fgetc) = url_mem_fgetc;
69     URLm(url, url_seek)  = url_mem_seek;
70     URLm(url, url_tell)  = url_mem_tell;
71     URLm(url, url_close) = url_mem_close;
72 
73     /* private members */
74     url->memory = memory;
75     url->memsiz = memsiz;
76     url->mempos = 0;
77     url->autofree = autofree;
78 
79     return (URL)url;
80 }
81 
url_mem_read(URL url,void * buff,long n)82 static long url_mem_read(URL url, void *buff, long n)
83 {
84     URL_mem *urlp = (URL_mem *)url;
85     long s;
86     char *p = (char *)buff;
87 
88     s = urlp->memsiz - urlp->mempos;
89     if(s > n)
90 	s = n;
91     if(s <= 0)
92 	return 0;
93     memcpy(p, urlp->memory + urlp->mempos, s);
94     urlp->mempos += s;
95     return s;
96 }
97 
url_mem_gets(URL url,char * buff,int n)98 static char *url_mem_gets(URL url, char *buff, int n)
99 {
100     URL_mem *urlp = (URL_mem *)url;
101     long s;
102     char *nlp, *p;
103 
104     if(urlp->memsiz == urlp->mempos)
105 	return NULL;
106     if(n <= 0)
107 	return buff;
108     if(n == 1)
109     {
110 	*buff = '\0';
111 	return buff;
112     }
113     n--; /* for '\0' */
114     s = urlp->memsiz - urlp->mempos;
115     if(s > n)
116 	s = n;
117     p = urlp->memory + urlp->mempos;
118     nlp = (char *)memchr(p, url_newline_code, s);
119     if(nlp != NULL)
120 	s = nlp - p + 1;
121     memcpy(buff, p, s);
122     buff[s] = '\0';
123     urlp->mempos += s;
124     return buff;
125 }
126 
url_mem_fgetc(URL url)127 static int url_mem_fgetc(URL url)
128 {
129     URL_mem *urlp = (URL_mem *)url;
130 
131     if(urlp->memsiz == urlp->mempos)
132 	return EOF;
133     return (int)(unsigned char)urlp->memory[urlp->mempos++];
134 }
135 
url_mem_seek(URL url,long offset,int whence)136 static long url_mem_seek(URL url, long offset, int whence)
137 {
138     URL_mem *urlp = (URL_mem *)url;
139     long ret;
140 
141     ret = urlp->mempos;
142     switch(whence)
143     {
144       case SEEK_SET:
145 	urlp->mempos = offset;
146 	break;
147       case SEEK_CUR:
148 	urlp->mempos += offset;
149 	break;
150       case SEEK_END:
151 	urlp->mempos = urlp->memsiz + offset;
152 	break;
153     }
154     if(urlp->mempos > urlp->memsiz)
155 	urlp->mempos = urlp->memsiz;
156     else if(urlp->mempos < 0)
157 	urlp->mempos = 0;
158 
159     return ret;
160 }
161 
url_mem_tell(URL url)162 static long url_mem_tell(URL url)
163 {
164     return ((URL_mem *)url)->mempos;
165 }
166 
url_mem_close(URL url)167 static void url_mem_close(URL url)
168 {
169     int save_errno = errno;
170     URL_mem *urlp = (URL_mem *)url;
171     if(urlp->autofree)
172 	free(urlp->memory);
173     free(url);
174     errno = save_errno;
175 }
176