1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 2003-2013 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                 Eclipse Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *          http://www.eclipse.org/org/documents/epl-v10.html           *
11 *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *                     Phong Vo <phongvo@gmail.com>                     *
18 *                                                                      *
19 ***********************************************************************/
20 #include	"vchdr.h"
21 
22 /*	Transforming rows by xor-ing.
23 **
24 **	Written by Kiem-Phong Vo
25 */
26 
27 #define SIZE		2	/* #bytes coding a record size	*/
28 #define MAXSIZE		(1 << 16) /* max record size		*/
29 #define GETSIZE(dt)	(((dt)[0]<<8)+(dt)[1]) /* get AMA size	*/
30 #define PUTSIZE(dt,v)	(((dt)[0] = (((v)>>8)&0377)), ((dt)[1] = ((v)&0377)) )
31 
32 /* Fast string xor-ing. Assumption: sizeof(type) is a power-of-2 <= 8 */
33 #define ALIGN(ptr,type)	(((unsigned char*)ptr - (unsigned char*)0) & (sizeof(type)-1) )
34 #define XOR(sx,s1,s2,sk,sn,algn,type) \
35 	do { if((sk+algn+sizeof(type)) <= sn) \
36 	     {	reg unsigned type *tx, *t1, *t2; \
37 	      	if(algn > 0) for(algn = sk+sizeof(type)-algn; sk < algn; ++sk) \
38 		    	*sx++ = *s1++ ^ *s2++; \
39 		tx = (unsigned type*)sx; t1 = (unsigned type*)s1; t2 = (unsigned type*)s2; \
40 		for(sn -= sizeof(type); sk <= sn; sk += sizeof(type)) \
41 		  	*tx++ = *t1++ ^ *t2++; \
42 		sn += sizeof(type); sx = (Vcchar_t*)tx; s1 = (Vcchar_t*)t1; s2 = (Vcchar_t*)t2; \
43 	     } \
44 	     for(; sk < sn; ++sk) \
45 		*sx++ = *s1++ ^ *s2++; \
46 	} while(0)
47 
48 #if __STD_C
amadiff(Vcodex_t * vc,const Void_t * data,size_t size,Void_t ** out)49 static ssize_t amadiff(Vcodex_t* vc, const Void_t* data, size_t size, Void_t** out)
50 #else
51 static ssize_t amadiff(vc, data, size, out)
52 Vcodex_t*	vc;
53 Void_t*		data;
54 size_t		size;
55 Void_t**	out;
56 #endif
57 {
58 	reg Vcchar_t	*dt, *df, *pd;
59 	ssize_t		k, a, ncols, sz, hdsz;
60 	Vcchar_t	*enddt, *output;
61 	Vcchar_t	*rcdt[MAXSIZE];
62 	Vcio_t		io;
63 	/**/DEBUG_DECLARE(int, i_align = 0)
64 	/**/DEBUG_DECLARE(int, s_align = 0)
65 
66 	vc->undone = 0;
67 	if(size == 0)
68 		return 0;
69 
70 	ncols = vc->disc ? vc->disc->size : 0;
71 	hdsz = vcsizeu(ncols);
72 	sz = ((hdsz + sizeof(int)-1)/sizeof(int))*sizeof(int);
73 	if(!(output = vcbuffer(vc, NIL(Vcchar_t*), size, sz)) )
74 		return -1;
75 
76 	df = output; enddt = (dt = (Vcchar_t*)data) + size;
77 	if(ncols > 0) /* fixed-length rows */
78 	{	if((sz = (size/ncols)*ncols) > 0)
79 		{	memcpy(df, dt, ncols);
80 			pd = dt; df += ncols; dt += ncols;
81 			if((sz -= ncols) > 0)
82 			{	k = 0;
83 				if((a = ALIGN(df,int)) == ALIGN(dt,int) && a == ALIGN(pd,int) )
84 					XOR(df, dt, pd, k, sz,  a, int);
85 				else if((a = ALIGN(df,short)) == ALIGN(dt,short) && a == ALIGN(pd,short) )
86 					XOR(df, dt, pd, k, sz,  a, short);
87 				else for(; k < sz; ++k)
88 					*df++ = *dt++ ^ *pd++;
89 			}
90 		}
91 	}
92 	else /* ama data */
93 	{	for(k = 0; k < MAXSIZE; ++k)
94 			rcdt[k] = NIL(Vcchar_t*);
95 		for(;;)
96 		{	if((dt+SIZE) > enddt)
97 				break;
98 			ncols = GETSIZE(dt);
99 			if((dt+ncols) > enddt)
100 				break;
101 
102 			pd = rcdt[ncols]; rcdt[ncols] = dt+SIZE;
103 			if(!pd)
104 			{	for(k = 0; k < ncols; ++k) /* first record is kept clear */
105 					*df++ = *dt++;
106 			}
107 			else
108 			{	for(k = 0; k < SIZE; ++k) /* record size is kept clear */
109 					*df++ = *dt++;
110 
111 				/* xor-transforming the rest of the data */
112 				if((a = ALIGN(df,int)) == ALIGN(dt,int) && a == ALIGN(pd,int))
113 					XOR(df, dt, pd, k, ncols, a, int);
114 				else if((a = ALIGN(df,short)) == ALIGN(dt,short) && a == ALIGN(pd,short) )
115 					XOR(df, dt, pd, k, ncols, a, short);
116 				else for(; k < ncols; ++k)
117 					*df++ = *dt++ ^ *pd++;
118 			}
119 		}
120 
121 		ncols = 0;
122 	}
123 
124 	vc->undone = enddt-dt;
125 	if((sz = dt - (Vcchar_t*)data) == 0)
126 		return 0;
127 
128 	dt = output;
129 	if(vcrecode(vc, &output, &sz, hdsz, 0) < 0 )
130 		return -1;
131 	if(dt != output)
132 		vcbuffer(vc, dt, -1, -1);
133 
134 	output -= hdsz; sz += hdsz;
135 	vcioinit(&io, output, hdsz);
136 	vcioputu(&io, ncols);
137 
138 	if(out)
139 		*out = output;
140 
141 	return sz;
142 }
143 
144 #if __STD_C
unamadiff(Vcodex_t * vc,const Void_t * data,size_t size,Void_t ** out)145 static ssize_t unamadiff(Vcodex_t* vc, const Void_t* data, size_t size, Void_t** out)
146 #else
147 static ssize_t unamadiff(vc, data, size, out)
148 Vcodex_t*	vc;
149 Void_t*		data;
150 size_t		size;
151 Void_t**	out;
152 #endif
153 {
154 	Vcchar_t	*dt, *df, *savdf, *pd, *enddt, *output;
155 	ssize_t		k, a, ncols, sz;
156 	Vcchar_t	*rcdt[MAXSIZE];
157 	Vcio_t		io;
158 
159 	vc->undone = 0;
160 	if(size == 0)
161 		return 0;
162 
163 	vcioinit(&io, data, size);
164 	ncols = vciogetu(&io);
165 
166 	df = savdf = vcionext(&io);
167 	sz = vciomore(&io);
168 	if(vcrecode(vc, &df, &sz, 0, 0) < 0 )
169 		return -1;
170 
171 	if(!(output = vcbuffer(vc, NIL(Vcchar_t*), sz, 0)) )
172 		return -1;
173 
174 	/* undo the transform */
175 	enddt = (dt = output) + sz;
176 	if(ncols > 0)
177 	{	if(sz%ncols != 0)
178 			return -1;
179 		memcpy(dt, df, ncols);
180 		for(pd = dt, df += ncols, dt += ncols; dt < enddt; )
181 			*dt++ = *df++ ^ *pd++;
182 	}
183 	else
184 	{	for(k = 0; k < MAXSIZE; ++k)
185 			rcdt[k] = NIL(Vcchar_t*);
186 		for(;;)
187 		{	if((dt+SIZE) > enddt)
188 				break;
189 			ncols = GETSIZE(df);
190 			if((dt+ncols) > enddt)
191 				return -1;
192 
193 			pd = rcdt[ncols]; rcdt[ncols] = dt+SIZE;
194 			if(!pd)
195 			{	for(k = 0; k < ncols; ++k)
196 					*dt++ = *df++;
197 			}
198 			else
199 			{	for(k = 0; k < SIZE; ++k)
200 					*dt++ = *df++;
201 
202 				/* xor-transforming the rest of the data */
203 				if((a = ALIGN(df,int)) == ALIGN(dt,int) && a == ALIGN(pd,int))
204 					XOR(dt, df, pd, k, ncols, a, int);
205 				else if((a = ALIGN(df,short)) == ALIGN(dt,short) && a == ALIGN(pd,short) )
206 					XOR(dt, df, pd, k, ncols, a, short);
207 				else for(; k < ncols; ++k)
208 					*dt++ = *df++ ^ *pd++;
209 			}
210 		}
211 	}
212 
213 	vcbuffer(vc, savdf, -1, -1);
214 
215 	if(out)
216 		*out = output;
217 	return sz;
218 }
219 
220 Vcmethod_t _Vcamadiff =
221 {	amadiff,
222 	unamadiff,
223 	0,
224 	"amadiff", "Xor-ing rows in an AMA table.",
225 	"[-?\n@(#)$Id: vcodex-amadiff (AT&T Research) 2003-01-01 $\n]" USAGE_LICENSE,
226 	0,
227 	1024*1024,
228 	0
229 };
230 
231 VCLIB(Vcamadiff)
232