bsdconv_malloc(size_t size)1 void *bsdconv_malloc(size_t size){
2 	return malloc(size);
3 }
4 
bsdconv_free(void * p)5 void bsdconv_free(void *p){
6 	free(p);
7 }
8 
bsdconv_mkstemp(char * template)9 int bsdconv_mkstemp(char *template){
10 	return mkstemp(template);
11 }
12 
getCodecDir()13 char * getCodecDir(){
14 	char *c;
15 	char *b;
16 	if((c=getenv("BSDCONV_PATH"))==NULL){
17 		c=BSDCONV_PATH;
18 	}
19 	b=malloc(strlen(c)+strlen(MODULES_SUBPATH)+2);
20 	sprintf(b, "%s/%s", c, MODULES_SUBPATH);
21 	return b;
22 }
23 
str2datum(const char * s,struct data_rt * d)24 int str2datum(const char *s, struct data_rt *d){
25 	d->data=NULL;
26 	d->len=0;
27 	if(!s)
28 		return EINVAL;
29 	d->data=malloc(strlen(s)/2);
30 	d->flags=F_FREE;
31 	d->next=NULL;
32 	char f=0;
33 	while(*s){
34 		if(hex[(unsigned char) *s]<0){
35 			free(d->data);
36 			d->data=NULL;
37 			return EINVAL;
38 		}
39 		switch(f){
40 			case 0:
41 				f=1;
42 				UCP(d->data)[d->len]=hex[(unsigned char)*s];
43 				break;
44 			case 1:
45 				f=0;
46 				UCP(d->data)[d->len]*=16;
47 				UCP(d->data)[d->len]+=hex[(unsigned char)*s];
48 				d->len+=1;
49 				break;
50 		}
51 		s+=1;
52 	}
53 	return 0;
54 }
55 
str2data(const char * _s,int * r,struct bsdconv_instance * ins)56 struct data_rt * str2data(const char *_s, int *r, struct bsdconv_instance *ins){
57 	struct data_rt ph;
58 	struct data_rt *t=&ph;
59 	char *k, *cur;
60 	char *s;
61 	char f;
62 
63 	ph.next=NULL;
64 	if(!_s){
65 		*r=EINVAL;
66 		return NULL;
67 	}
68 	if(!*_s){
69 		*r=0;
70 		return NULL;
71 	}
72 
73 	s=strdup(_s);
74 
75 	cur=s;
76 	while((k=strsep(&cur, "."))!=NULL){
77 		t->next=malloc(sizeof(struct data_rt));
78 		t=t->next;
79 		t->next=NULL;
80 		t->len=0;
81 		t->flags=F_FREE;
82 		t->data=malloc(strlen(k)/2);
83 		f=0;
84 		while(*k){
85 			if(hex[(unsigned char) *k]<0){
86 				DATA_FREE(ins, ph.next);
87 				*r=EINVAL;
88 				free(s);
89 				return NULL;
90 			}
91 			switch(f){
92 				case 0:
93 					f=1;
94 					UCP(t->data)[t->len]=hex[(unsigned char)*k];
95 					break;
96 				case 1:
97 					f=0;
98 					UCP(t->data)[t->len]*=16;
99 					UCP(t->data)[t->len]+=hex[(unsigned char)*k];
100 					t->len+=1;
101 					break;
102 			}
103 			k+=1;
104 		}
105 	}
106 
107 	free(s);
108 
109 	*r=0;
110 	return ph.next;
111 }
112 
bsdconv_get_phase_index(struct bsdconv_instance * ins,int phasen)113 int bsdconv_get_phase_index(struct bsdconv_instance *ins, int phasen){
114 	/*
115 	 * phase[0] is a place holder for _INPUT
116 	 * real phases range is [1,len]=[1,phasen]
117 	 */
118 	/* logical new index = len */
119 	if(phasen /* logical */ >= ins->phasen /* len */){
120 		/* real  = logical + 1 */
121 		return ins->phasen + 1;
122 	}else{
123 		/* real  = (n + len) % (len) + 1*/
124 		return (phasen + ins->phasen) % (ins->phasen) + 1;
125 	}
126 }
127 
bsdconv_get_codec_index(struct bsdconv_instance * ins,int phasen,int codecn)128 int bsdconv_get_codec_index(struct bsdconv_instance *ins, int phasen, int codecn){
129 	/*
130 	 * codecn is -=1 for convenient use as boundary
131 	 * real phases range is [0,len)=[0,codecn]
132 	 */
133 	phasen=bsdconv_get_phase_index(ins, phasen);
134 
135 	/* logical new index = len */
136 	if(codecn /* logical */ >= ins->phase[phasen].codecn+1 /* len */ ){
137 		/* real  = logical */
138 		return ins->phase[phasen].codecn+1;
139 	}else{
140 		/* real  = (n + len) % (len) */
141 		return (codecn + ins->phase[phasen].codecn+1) % (ins->phase[phasen].codecn+1);
142 	}
143 }
144 
bsdconv_insert_phase(const char * conversion,const char * codec,int phase_type,int ophasen)145 char * bsdconv_insert_phase(const char *conversion, const char *codec, int phase_type, int ophasen){
146 	struct bsdconv_instance *ins;
147 	int i,j;
148 	char *ret;
149 
150 	ins=bsdconv_unpack(conversion);
151 	if(!ins){
152 		return NULL;
153 	}
154 
155 	int phasen=bsdconv_get_phase_index(ins, ophasen);
156 
157 	ins->phasen+=1;
158 	ins->phase=realloc(ins->phase, sizeof(struct bsdconv_phase) * (ins->phasen+1));
159 
160 	for(i=ins->phasen /* shifted index */;i>phasen;--i){
161 		ins->phase[i]=ins->phase[i-1];
162 	}
163 	ins->phase[phasen].type=phase_type;
164 	ins->phase[phasen].codec=malloc(sizeof(struct bsdconv_codec));
165 	ins->phase[phasen].codecn=0 /* trimmed length */;
166 
167 	ins->phase[phasen].codec[0].desc=strdup(codec);
168 	ins->phase[phasen].codec[0].argv=NULL;
169 
170 	ret=bsdconv_pack(ins);
171 
172 	for(i=1;i<=ins->phasen;++i){
173 		for(j=0;j<=ins->phase[i].codecn;++j){
174 			free(ins->phase[i].codec[j].desc);
175 		}
176 		free(ins->phase[i].codec);
177 	}
178 	free(ins->phase);
179 	free(ins);
180 
181 	return ret;
182 }
183 
bsdconv_insert_codec(const char * conversion,const char * codec,int ophasen,int ocodecn)184 char * bsdconv_insert_codec(const char *conversion, const char *codec, int ophasen, int ocodecn){
185 	struct bsdconv_instance *ins;
186 	int i,j;
187 	char *ret;
188 
189 	ins=bsdconv_unpack(conversion);
190 	if(!ins){
191 		return NULL;
192 	}
193 
194 	int phasen=bsdconv_get_phase_index(ins, ophasen);
195 	int codecn=bsdconv_get_codec_index(ins, ophasen, ocodecn);
196 
197 	++ins->phase[phasen].codecn;
198 	ins->phase[phasen].codec=realloc(ins->phase[phasen].codec, sizeof(struct bsdconv_codec)*(ins->phase[phasen].codecn+1));
199 
200 	for(i=ins->phase[phasen].codecn;i>codecn;--i){
201 		ins->phase[phasen].codec[i]=ins->phase[phasen].codec[i-1];
202 	}
203 	ins->phase[phasen].codec[codecn].desc=strdup(codec);
204 	ins->phase[phasen].codec[codecn].argv=NULL;
205 
206 	ret=bsdconv_pack(ins);
207 
208 	for(i=1;i<=ins->phasen;++i){
209 		for(j=0;j<=ins->phase[i].codecn;++j){
210 			free(ins->phase[i].codec[j].desc);
211 		}
212 		free(ins->phase[i].codec);
213 	}
214 	free(ins->phase);
215 	free(ins);
216 
217 	return ret;
218 }
219 
bsdconv_replace_phase(const char * conversion,const char * codec,int phase_type,int ophasen)220 char * bsdconv_replace_phase(const char *conversion, const char *codec, int phase_type, int ophasen){
221 	struct bsdconv_instance *ins;
222 	int i,j;
223 	char *ret;
224 
225 	ins=bsdconv_unpack(conversion);
226 	if(!ins){
227 		return NULL;
228 	}
229 
230 	int phasen=bsdconv_get_phase_index(ins, ophasen);
231 
232 	for(j=0;j<=ins->phase[phasen].codecn;++j){
233 		free(ins->phase[phasen].codec[j].desc);
234 	}
235 
236 	ins->phase[phasen].type=phase_type;
237 	ins->phase[phasen].codecn=0 /* trimmed length */;
238 	ins->phase[phasen].codec[0].desc=strdup(codec);
239 	ins->phase[phasen].codec[0].argv=NULL;
240 
241 	ret=bsdconv_pack(ins);
242 
243 	for(i=1;i<=ins->phasen;++i){
244 		for(j=0;j<=ins->phase[i].codecn;++j){
245 			free(ins->phase[i].codec[j].desc);
246 		}
247 		free(ins->phase[i].codec);
248 	}
249 	free(ins->phase);
250 	free(ins);
251 
252 	return ret;
253 }
254 
bsdconv_replace_codec(const char * conversion,const char * codec,int ophasen,int ocodecn)255 char * bsdconv_replace_codec(const char *conversion, const char *codec, int ophasen, int ocodecn){
256 	struct bsdconv_instance *ins;
257 	int i,j;
258 	char *ret;
259 
260 	ins=bsdconv_unpack(conversion);
261 	if(!ins){
262 		return NULL;
263 	}
264 
265 	int phasen=bsdconv_get_phase_index(ins, ophasen);
266 	int codecn=bsdconv_get_codec_index(ins, ophasen, ocodecn);
267 
268 	free(ins->phase[phasen].codec[codecn].desc);
269 	ins->phase[phasen].codec[codecn].desc=strdup(codec);
270 	ins->phase[phasen].codec[codecn].argv=NULL;
271 
272 	ret=bsdconv_pack(ins);
273 
274 	for(i=1;i<=ins->phasen;++i){
275 		for(j=0;j<=ins->phase[i].codecn;++j){
276 			free(ins->phase[i].codec[j].desc);
277 		}
278 		free(ins->phase[i].codec);
279 	}
280 	free(ins->phase);
281 	free(ins);
282 
283 	return ret;
284 }
285