xref: /plan9/sys/src/libc/port/encodefmt.c (revision 59c21d95eabd8f0704c9b4a4cb647ed908ae2da6)
19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
3*59c21d95SDavid du Colombier #include <ctype.h>
49a747e4fSDavid du Colombier 
59a747e4fSDavid du Colombier int
encodefmt(Fmt * f)69a747e4fSDavid du Colombier encodefmt(Fmt *f)
79a747e4fSDavid du Colombier {
89a747e4fSDavid du Colombier 	char *out;
99a747e4fSDavid du Colombier 	char *buf;
109a747e4fSDavid du Colombier 	int len;
119a747e4fSDavid du Colombier 	int ilen;
129a747e4fSDavid du Colombier 	int rv;
139a747e4fSDavid du Colombier 	uchar *b;
14*59c21d95SDavid du Colombier 	char *p;
159a747e4fSDavid du Colombier 	char obuf[64];	// rsc optimization
169a747e4fSDavid du Colombier 
179a747e4fSDavid du Colombier 	if(!(f->flags&FmtPrec) || f->prec < 1)
189a747e4fSDavid du Colombier 		goto error;
199a747e4fSDavid du Colombier 
209a747e4fSDavid du Colombier 	b = va_arg(f->args, uchar*);
217fd46167SDavid du Colombier 	if(b == 0)
227fd46167SDavid du Colombier 		return fmtstrcpy(f, "<nil>");
239a747e4fSDavid du Colombier 
249a747e4fSDavid du Colombier 	ilen = f->prec;
259a747e4fSDavid du Colombier 	f->prec = 0;
269a747e4fSDavid du Colombier 	f->flags &= ~FmtPrec;
279a747e4fSDavid du Colombier 	switch(f->r){
289a747e4fSDavid du Colombier 	case '<':
299a747e4fSDavid du Colombier 		len = (8*ilen+4)/5 + 3;
309a747e4fSDavid du Colombier 		break;
319a747e4fSDavid du Colombier 	case '[':
329a747e4fSDavid du Colombier 		len = (8*ilen+5)/6 + 4;
339a747e4fSDavid du Colombier 		break;
349a747e4fSDavid du Colombier 	case 'H':
359a747e4fSDavid du Colombier 		len = 2*ilen + 1;
369a747e4fSDavid du Colombier 		break;
379a747e4fSDavid du Colombier 	default:
389a747e4fSDavid du Colombier 		goto error;
399a747e4fSDavid du Colombier 	}
409a747e4fSDavid du Colombier 
419a747e4fSDavid du Colombier 	if(len > sizeof(obuf)){
429a747e4fSDavid du Colombier 		buf = malloc(len);
439a747e4fSDavid du Colombier 		if(buf == nil)
449a747e4fSDavid du Colombier 			goto error;
459a747e4fSDavid du Colombier 	} else
469a747e4fSDavid du Colombier 		buf = obuf;
479a747e4fSDavid du Colombier 
489a747e4fSDavid du Colombier 	// convert
499a747e4fSDavid du Colombier 	out = buf;
509a747e4fSDavid du Colombier 	switch(f->r){
519a747e4fSDavid du Colombier 	case '<':
529a747e4fSDavid du Colombier 		rv = enc32(out, len, b, ilen);
539a747e4fSDavid du Colombier 		break;
549a747e4fSDavid du Colombier 	case '[':
559a747e4fSDavid du Colombier 		rv = enc64(out, len, b, ilen);
569a747e4fSDavid du Colombier 		break;
579a747e4fSDavid du Colombier 	case 'H':
589a747e4fSDavid du Colombier 		rv = enc16(out, len, b, ilen);
59*59c21d95SDavid du Colombier 		if(rv >= 0 && (f->flags & FmtLong))
60*59c21d95SDavid du Colombier 			for(p = buf; *p; p++)
61*59c21d95SDavid du Colombier 				*p = tolower(*p);
629a747e4fSDavid du Colombier 		break;
639a747e4fSDavid du Colombier 	default:
649a747e4fSDavid du Colombier 		rv = -1;
659a747e4fSDavid du Colombier 		break;
669a747e4fSDavid du Colombier 	}
679a747e4fSDavid du Colombier 	if(rv < 0)
689a747e4fSDavid du Colombier 		goto error;
699a747e4fSDavid du Colombier 
709a747e4fSDavid du Colombier 	fmtstrcpy(f, buf);
719a747e4fSDavid du Colombier 	if(buf != obuf)
729a747e4fSDavid du Colombier 		free(buf);
739a747e4fSDavid du Colombier 	return 0;
749a747e4fSDavid du Colombier 
759a747e4fSDavid du Colombier error:
769a747e4fSDavid du Colombier 	return fmtstrcpy(f, "<encodefmt>");
779a747e4fSDavid du Colombier }
78