Files
mars-tinyldap/fmt_asn1generic.c
leitner e04ca78ff8 add "generic" format string based encoder and decoder (scan_asn1generic,
fmt_asn1generic, see t10.c for example usage)
add "generic" asn.1 dumper (in t10.c)
fix some read off-by-one errors, minor cleanups
add real OID support
add bitstring support
2011-04-28 19:50:11 +00:00

77 lines
2.2 KiB
C

#include <stdarg.h>
#include <string.h>
#include "asn1.h"
size_t fmt_asn1generic(char* dest,const char* fmt,...) {
size_t containerstack[100];
size_t curinstack=0;
va_list args;
va_start(args,fmt);
unsigned long* application=0;
struct string* s;
struct string S;
size_t curlen=0;
size_t cursor=0;
size_t seqlen;
unsigned long appstore;
while (*fmt) {
char* realdest=dest?dest+cursor:NULL;
switch (*fmt) {
case 'a': // make next tag use APPLICATION with this tag
appstore=va_arg(args,unsigned long);
application=&appstore;
break;
case 'i': // send integer
{
unsigned long i=va_arg(args,unsigned long);
if (application)
curlen=fmt_asn1int(realdest,APPLICATION,PRIMITIVE,*application,i);
else
curlen=fmt_asn1int(realdest,UNIVERSAL,PRIMITIVE,INTEGER,i);
application=NULL;
break;
}
case 'S': // send OCTET_STRING, using struct string* as arg
s=va_arg(args,struct string*);
copystring:
if (application)
curlen=fmt_asn1string(realdest,APPLICATION,PRIMITIVE,*application,s->s,s->l);
else
curlen=fmt_asn1string(realdest,UNIVERSAL,PRIMITIVE,OCTET_STRING,s->s,s->l);
application=NULL;
break;
case 's': // send OCTET_STRING, using const char* with strlen() as arg
S.s=va_arg(args,const char*);
S.l=strlen(S.s);
s=&S;
goto copystring;
case '{': // start SEQUENCE
if (application)
curlen=fmt_asn1tag(realdest,APPLICATION,CONSTRUCTED,*application);
else
curlen=fmt_asn1tag(realdest,UNIVERSAL,CONSTRUCTED,SEQUENCE_OF);
containerstack[curinstack++]=cursor+curlen;
application=NULL;
break;
case '}': // end of SEQUENCE
/* we just wrote the tag and the sequence. Now that we wrote the
* sequence, we know the length it took, and we need to move the
* sequence data backwards to make room to write the ASN.1 length */
{
char* anfang;
if (!curinstack) return 0;
anfang=dest+containerstack[--curinstack];
seqlen=dest+cursor-anfang;
curlen=fmt_asn1length(NULL,seqlen);
if (!dest) break;
memmove(anfang+curlen,anfang,seqlen);
fmt_asn1length(anfang,seqlen);
break;
}
}
cursor+=curlen;
++fmt;
}
return cursor;
}