xref: /plan9/sys/src/liboventi/pack.c (revision 368c31ab13393dea083228fdd1c3445076f83a4b)
1 #include <u.h>
2 #include <libc.h>
3 #include <oventi.h>
4 
5 /*
6  * integer conversion routines
7  */
8 #define	U8GET(p)	((p)[0])
9 #define	U16GET(p)	(((p)[0]<<8)|(p)[1])
10 #define	U32GET(p)	((u32int)(((p)[0]<<24)|((p)[1]<<16)|((p)[2]<<8)|(p)[3]))
11 #define	U48GET(p)	(((vlong)U16GET(p)<<32)|(vlong)U32GET((p)+2))
12 #define	U64GET(p)	(((vlong)U32GET(p)<<32)|(vlong)U32GET((p)+4))
13 
14 #define	U8PUT(p,v)	(p)[0]=(v)
15 #define	U16PUT(p,v)	(p)[0]=(v)>>8;(p)[1]=(v)
16 #define	U32PUT(p,v)	(p)[0]=(v)>>24;(p)[1]=(v)>>16;(p)[2]=(v)>>8;(p)[3]=(v)
17 #define	U48PUT(p,v,t32)	t32=(v)>>32;U16PUT(p,t32);t32=(v);U32PUT((p)+2,t32)
18 #define	U64PUT(p,v,t32)	t32=(v)>>32;U32PUT(p,t32);t32=(v);U32PUT((p)+4,t32)
19 
20 static int
checkSize(int n)21 checkSize(int n)
22 {
23 	if(n < 256 || n > VtMaxLumpSize) {
24 		vtSetError("bad block size");
25 		return 0;
26 	}
27 	return 1;
28 }
29 
30 
31 void
vtRootPack(VtRoot * r,uchar * p)32 vtRootPack(VtRoot *r, uchar *p)
33 {
34 	uchar *op = p;
35 
36 	U16PUT(p, r->version);
37 	p += 2;
38 	memmove(p, r->name, sizeof(r->name));
39 	p += sizeof(r->name);
40 	memmove(p, r->type, sizeof(r->type));
41 	p += sizeof(r->type);
42 	memmove(p, r->score, VtScoreSize);
43 	p +=  VtScoreSize;
44 	U16PUT(p, r->blockSize);
45 	p += 2;
46 	memmove(p, r->prev, VtScoreSize);
47 	p += VtScoreSize;
48 
49 	assert(p-op == VtRootSize);
50 }
51 
52 int
vtRootUnpack(VtRoot * r,uchar * p)53 vtRootUnpack(VtRoot *r, uchar *p)
54 {
55 	uchar *op = p;
56 
57 	memset(r, 0, sizeof(*r));
58 
59 	r->version = U16GET(p);
60 	if(r->version != VtRootVersion) {
61 		vtSetError("unknown root version");
62 		return 0;
63 	}
64 	p += 2;
65 	memmove(r->name, p, sizeof(r->name));
66 	r->name[sizeof(r->name)-1] = 0;
67 	p += sizeof(r->name);
68 	memmove(r->type, p, sizeof(r->type));
69 	r->type[sizeof(r->type)-1] = 0;
70 	p += sizeof(r->type);
71 	memmove(r->score, p, VtScoreSize);
72 	p +=  VtScoreSize;
73 	r->blockSize = U16GET(p);
74 	if(!checkSize(r->blockSize))
75 		return 0;
76 	p += 2;
77 	memmove(r->prev, p, VtScoreSize);
78 	p += VtScoreSize;
79 
80 	assert(p-op == VtRootSize);
81 	return 1;
82 }
83 
84 void
vtEntryPack(VtEntry * e,uchar * p,int index)85 vtEntryPack(VtEntry *e, uchar *p, int index)
86 {
87 	ulong t32;
88 	int flags;
89 	uchar *op;
90 
91 	p += index * VtEntrySize;
92 	op = p;
93 
94 	U32PUT(p, e->gen);
95 	p += 4;
96 	U16PUT(p, e->psize);
97 	p += 2;
98 	U16PUT(p, e->dsize);
99 	p += 2;
100 	flags = e->flags | ((e->depth << VtEntryDepthShift) & VtEntryDepthMask);
101 	U8PUT(p, flags);
102 	p++;
103 	memset(p, 0, 5);
104 	p += 5;
105 	U48PUT(p, e->size, t32);
106 	p += 6;
107 	memmove(p, e->score, VtScoreSize);
108 	p += VtScoreSize;
109 
110 	assert(p-op == VtEntrySize);
111 }
112 
113 int
vtEntryUnpack(VtEntry * e,uchar * p,int index)114 vtEntryUnpack(VtEntry *e, uchar *p, int index)
115 {
116 	uchar *op;
117 
118 	p += index * VtEntrySize;
119 	op = p;
120 
121 	e->gen = U32GET(p);
122 	p += 4;
123 	e->psize = U16GET(p);
124 	p += 2;
125 	e->dsize = U16GET(p);
126 	p += 2;
127 	e->flags = U8GET(p);
128 	e->depth = (e->flags & VtEntryDepthMask) >> VtEntryDepthShift;
129 	e->flags &= ~VtEntryDepthMask;
130 	p++;
131 	p += 5;
132 	e->size = U48GET(p);
133 	p += 6;
134 	memmove(e->score, p, VtScoreSize);
135 	p += VtScoreSize;
136 
137 	assert(p-op == VtEntrySize);
138 
139 	if(!(e->flags & VtEntryActive))
140 		return 1;
141 
142 	if(!checkSize(e->psize) || !checkSize(e->dsize))
143 		return 0;
144 
145 	return 1;
146 }
147 
148