add netstring formatter
fix scan_netstring to actually correctly return the length of the transported string add documentation
This commit is contained in:
parent
fb1f19042f
commit
6859c4b6ca
35
fmt.h
35
fmt.h
@ -10,6 +10,8 @@
|
||||
#include <sys/types.h>
|
||||
/* for byte_copy */
|
||||
#include "byte.h"
|
||||
/* for add_of */
|
||||
#include "rangecheck.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -143,10 +145,43 @@ size_t fmt_iso8601(char* dest,time_t t);
|
||||
#define FMT_UTF8 5
|
||||
#define FMT_ASN1LENGTH 17 /* enough space to hold 2^128-1 */
|
||||
#define FMT_ASN1TAG 19 /* enough space to hold 2^128-1 */
|
||||
|
||||
/* some variable length encodings for integers */
|
||||
size_t fmt_utf8(char* dest,uint32_t n); /* can store 0-0x7fffffff */
|
||||
size_t fmt_asn1derlength(char* dest,unsigned long long l); /* 0-0x7f: 1 byte, above that 1+bytes_needed bytes */
|
||||
size_t fmt_asn1dertag(char* dest,unsigned long long l); /* 1 byte for each 7 bits; upper bit = more bytes coming */
|
||||
size_t fmt_varint(char* dest,unsigned long long l); /* protocol buffers encoding; like asn1dertag but little endian */
|
||||
size_t fmt_pb_tag(char* dest,size_t fieldno,unsigned char type); /* protocol buffer tag */
|
||||
size_t fmt_pb_type0_int(char* dest,signed long long l); /* protocol buffers encoding: type 0 integer */
|
||||
size_t fmt_pb_type1_double(char* dest,double d); /* protocol buffers encoding: double (64-bit little endian blob) */
|
||||
size_t fmt_pb_type1_fixed64(char* dest,uint64_t l); /* protocol buffers encoding: 64-bit little endian blob */
|
||||
size_t fmt_pb_type2_string(char* dest,const char* s,size_t l); /* protocol buffers encoding: varint length + blob */
|
||||
size_t fmt_pb_type5_float(char* dest,float f); /* protocol buffers encoding: float (32-bit little endian blob) */
|
||||
size_t fmt_pb_type5_fixed32(char* dest,uint32_t l); /* protocol buffers encoding: 32-bit little endian blob */
|
||||
|
||||
static inline size_t fmt_pb_int(char* dest,size_t fieldno,signed long long l) {
|
||||
size_t n=fmt_pb_tag(dest,fieldno,0);
|
||||
return n+fmt_pb_type0_int(dest?dest+n:0,l);
|
||||
}
|
||||
|
||||
static inline size_t fmt_pb_double(char* dest,size_t fieldno,double d) {
|
||||
size_t n=fmt_pb_tag(dest,fieldno,1);
|
||||
return n+fmt_pb_type1_double(dest?dest+n:0,d);
|
||||
}
|
||||
|
||||
static inline size_t fmt_pb_float(char* dest,size_t fieldno,float f) {
|
||||
size_t n=fmt_pb_tag(dest,fieldno,5);
|
||||
return n+fmt_pb_type5_float(dest?dest+n:0,f);
|
||||
}
|
||||
|
||||
static inline size_t fmt_pb_string(char* dest,size_t fieldno,const char* s,size_t l) {
|
||||
size_t n=fmt_pb_tag(dest,fieldno,2);
|
||||
size_t m;
|
||||
if (add_of(m,fmt_pb_type2_string(NULL,s,l),n)) return 0;
|
||||
return n+fmt_pb_type2_string(dest?dest+n:0,s,l);
|
||||
}
|
||||
|
||||
size_t fmt_netstring(char* dest,const char* src,size_t len);
|
||||
|
||||
/* Marshaling helper functions.
|
||||
* Escape one character, no matter if it needs escaping or not.
|
||||
|
29
fmt/fmt_netstring.3
Normal file
29
fmt/fmt_netstring.3
Normal file
@ -0,0 +1,29 @@
|
||||
.TH fmt_netstring 3
|
||||
.SH NAME
|
||||
fmt_netstring \- convert a memory buffer into a netstring
|
||||
.SH SYNTAX
|
||||
.B #include <fmt.h>
|
||||
|
||||
size_t \fBfmt_netstring\fP(char *\fIdest\fR,const char *\fIsource\fR,
|
||||
size_t \fIlen\fR);
|
||||
.SH DESCRIPTION
|
||||
fmt_netstring creates a netstring from a raw memory buffer and returns
|
||||
the length.
|
||||
|
||||
fmt_netstring does not append \\0.
|
||||
|
||||
If \fIdest\fR equals FMT_LEN (i.e. is zero), fmt_netstring returns the number
|
||||
of bytes it would have written.
|
||||
.SH "RETURN VALUE"
|
||||
fmt_netstring returns the number of bytes written (or that would have
|
||||
been written, had the destination pointer not pointed to NULL).
|
||||
|
||||
If the input buffer is implausibly large, fmt_netstring returns 0
|
||||
instead.
|
||||
.SH EXAMPLE
|
||||
The raw memory buffer "foo" would become the netstring "3:foo,"
|
||||
.SH SPEC
|
||||
http://cr.yp.to/proto/netstrings.txt
|
||||
|
||||
.SH "SEE ALSO"
|
||||
scan_netstring(3)
|
15
fmt/fmt_netstring.c
Normal file
15
fmt/fmt_netstring.c
Normal file
@ -0,0 +1,15 @@
|
||||
#include "fmt.h"
|
||||
#include "rangecheck.h"
|
||||
#include <string.h>
|
||||
|
||||
size_t fmt_netstring(char* dest,const char* src,size_t len) {
|
||||
size_t n=fmt_ulong(NULL,len);
|
||||
size_t m;
|
||||
if (!range_validbuf(src,len) || add_of(m,len,n+2)) return 0; /* n came from fmt_ulong, so it is a very small number, below 50 */
|
||||
if (!dest) return m;
|
||||
fmt_ulong(dest,len); dest+=n;
|
||||
*dest++=':';
|
||||
memcpy(dest,src,len);
|
||||
dest[len]=',';
|
||||
return m;
|
||||
}
|
27
scan/scan_netstring.3
Normal file
27
scan/scan_netstring.3
Normal file
@ -0,0 +1,27 @@
|
||||
.TH scan_netstring 3
|
||||
.SH NAME
|
||||
scan_netstring \- parse a netstring
|
||||
.SH SYNTAX
|
||||
.B #include <scan.h>
|
||||
|
||||
size_t \fBscan_netstring\fP(const char *\fIin\fR,size_t len,char** \fIdest\fR, size_t *\fIslen\fR);
|
||||
.SH DESCRIPTION
|
||||
scan_netstring attempts to parse the netstring in the input buffer
|
||||
(in,len). If the buffer contains a valid netstring, then (*dest,*slen)
|
||||
is set to the start and length of the transported string.
|
||||
|
||||
Note that this string is not zero terminated. No copy is made.
|
||||
scan_netstring points it inside the input buffer.
|
||||
.SH "RETURN VALUE"
|
||||
scan_netstring returns the number of bytes in the netstring (the outer
|
||||
representation, not the transported inner string) if parsing worked, or
|
||||
0 if the input buffer did not contain a valid (or full) netstring.
|
||||
|
||||
.SH EXAMPLE
|
||||
The raw memory buffer "foo" would become the netstring "3:foo,"
|
||||
.SH SPEC
|
||||
http://cr.yp.to/proto/netstrings.txt
|
||||
|
||||
.SH "SEE ALSO"
|
||||
fmt_netstring(3)
|
||||
|
@ -20,6 +20,6 @@ size_t scan_netstring(const char* in,size_t len,char** dest,size_t* slen) {
|
||||
in[n+l+1]!=',')
|
||||
return 0;
|
||||
*dest=(char*)in+n+1;
|
||||
*slen=n;
|
||||
*slen=l;
|
||||
return n+2+l;
|
||||
}
|
||||
|
20
test/netstring.c
Normal file
20
test/netstring.c
Normal file
@ -0,0 +1,20 @@
|
||||
#include "fmt.h"
|
||||
#include "scan.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
char buf[100];
|
||||
char* s;
|
||||
size_t l;
|
||||
const char* orig;
|
||||
assert(fmt_netstring(buf,"hello world!",12)==16 && !memcmp(buf,"12:hello world!,",16));
|
||||
assert(scan_netstring(buf,16,&s,&l)==16 && s==buf+3 && l==12);
|
||||
|
||||
orig="3:foo,"; assert(scan_netstring(orig,6,&s,&l)==6 && s==orig+2 && l==3);
|
||||
orig="4294967295:foo,"; assert(scan_netstring(orig,15,&s,&l)==0);
|
||||
orig="18446744073709551615:foo,"; assert(scan_netstring(orig,25,&s,&l)==0);
|
||||
|
||||
assert(fmt_netstring(buf,orig,(size_t)-1)==0);
|
||||
assert(fmt_netstring(buf,NULL,(size_t)-1)==0);
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
#include "scan.h"
|
||||
#include <assert.h>
|
||||
|
||||
int main() {
|
||||
char* s;
|
||||
size_t l;
|
||||
const char* orig;
|
||||
orig="3:foo,"; assert(scan_netstring(orig,6,&s,&l)==6); assert(s==orig+2);
|
||||
orig="4294967295:foo,"; assert(scan_netstring(orig,15,&s,&l)==0);
|
||||
orig="18446744073709551615:foo,"; assert(scan_netstring(orig,25,&s,&l)==0);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user