GSI Object Oriented Online Offline (Go4)  GO4-6.3.0
f_ut_compress.c
Go to the documentation of this file.
1 // $Id$
2 //-----------------------------------------------------------------------
3 // The GSI Online Offline Object Oriented (Go4) Project
4 // Experiment Data Processing at EE department, GSI
5 //-----------------------------------------------------------------------
6 // Copyright (C) 2000- GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
7 // Planckstr. 1, 64291 Darmstadt, Germany
8 // Contact: http://go4.gsi.de
9 //-----------------------------------------------------------------------
10 // This software can be used under the license agreements as stated
11 // in Go4License.txt file which is part of the distribution.
12 //-----------------------------------------------------------------------
13 
14 /* type definitions */
15 #include "typedefs.h"
16 #include "f_ut_compress.h"
17 #include <stdio.h>
18 
19 #define PACK(bit) if(*pc_in != 0){*pl_mask += bit ; *pc_out++ = *pc_in; } pc_in++;
20 
21 #ifdef GSI__LINUX
22 #define UNPACK(bit) if(l_mask & bit ) *pc_out++ = *pc_in++; else *pc_out++ = 0;
23 #endif
24 #ifdef GSI__NT
25 #define UNPACK(bit) if(l_mask & bit ) *pc_out++ = *pc_in++; else *pc_out++ = 0;
26 #endif
27 #ifdef GSI__WINNT
28 #define UNPACK(bit) if(l_mask & bit ) *pc_out++ = *pc_in++; else *pc_out++ = 0;
29 #endif
30 #ifdef GSI__VMS
31 #define UNPACK(bit) if(l_mask & bit ) *pc_out = *pc_in++; pc_out++;
32 #endif
33 #ifdef GSI__AIX
34 #define UNPACK(bit) if(l_mask & bit ) *pc_out = *pc_in++; pc_out++;
35 #endif
36 #ifdef GSI__SOLARIS
37 #define UNPACK(bit) if(l_mask & bit ) *pc_out = *pc_in++; pc_out++;
38 #endif
39 #ifdef GSI__LYNX
40 #define UNPACK(bit) if(l_mask & bit ) *pc_out = *pc_in++; pc_out++;
41 #endif
42 /*****************+***********+****************************************/
43 /* */
44 /* GSI, Gesellschaft fuer Schwerionenforschung mbH */
45 /* Postfach 11 05 41 */
46 /* D-6100 Darmstadt 11 */
47 /* */
48 /*1+ C Procedure ***********+******************************************/
49 /* */
50 /*+ Module : f_ut_compr_size */
51 /* */
52 /*--------------------------------------------------------------------*/
53 /*+ CALLING : size=f_ut_compr_size(*input,inlen) */
54 /*--------------------------------------------------------------------*/
55 /* */
56 /*+ PURPOSE : return size of compressed data field. */
57 /* */
58 /*+ ARGUMENTS : */
59 /* */
60 /*+ input : (INTU1 *) Pointer to data field. */
61 /*+ inlen : (INTS4) Length of input data field [bytes]. */
62 /* */
63 /*+ Return type : INTS4 */
64 /*+ return : Number of bytes of compressed output */
65 /*+ Include name: f_ut_compress.h */
66 /* */
67 /*2+Implementation************+****************************************/
68 /* */
69 /*+ Version : 1.01 */
70 /*+ Author : H.G.Essel */
71 /*+ Last Update : 13-Jul-2000 */
72 /* */
73 /*2+Internals*****+***********+****************************************/
74 /* */
75 /*+ Utility : UTIL */
76 /*+ Created : 07-Jul-2000 */
77 /* */
78 /*1- C Procedure ***********+******************************************/
79 INTS4 f_ut_compr_size(INTU1 *pc_input,INTS4 l_inlen)
80 {
81 INTU4 l_bytes;
82 INTU4 l_masks;
83 INTU4 *pl_mask,*pl_end;
84 
85 l_bytes=0;
86 pl_mask=(INTU4 *)pc_input;
87 pl_end=pl_mask+l_inlen/4;
88 while(pl_mask!=pl_end)
89 {
90  if(*pl_mask&0x000000ff) l_bytes++;
91  if(*pl_mask&0x0000ff00) l_bytes++;
92  if(*pl_mask&0x00ff0000) l_bytes++;
93  if(*pl_mask&0xff000000) l_bytes++;
94  pl_mask++;
95 }
96 if(l_bytes%4 != 0) l_bytes=l_bytes+4-l_bytes%4;
97 l_masks=(l_inlen >> 5);
98 if(l_inlen%32 != 0) l_masks++;
99 return(l_bytes+4*l_masks+sizeof(s_compress));
100 }
101 
102 /*1+ C Procedure ***********+******************************************/
103 /* */
104 /*+ Module : f_ut_compr_zeros */
105 /* */
106 /*--------------------------------------------------------------------*/
107 /*+ CALLING : zeros=f_ut_compr_zeros(*input,inlen) */
108 /*--------------------------------------------------------------------*/
109 /* */
110 /*+ PURPOSE : return % zero bytes. */
111 /* */
112 /*+ ARGUMENTS : */
113 /* */
114 /*+ input : (INTU1 *) Pointer to data field. */
115 /*+ inlen : (INTS4) Length of input data field [bytes]. */
116 /* */
117 /*+ Return type : INTS4 */
118 /*+ return : % of zero bytes */
119 /*+ Include name: f_ut_compress.h */
120 /* */
121 /*2+Implementation************+****************************************/
122 /* */
123 /*+ Version : 1.01 */
124 /*+ Author : H.G.Essel */
125 /*+ Last Update : 13-Jul-2000 */
126 /* */
127 /*2+Internals*****+***********+****************************************/
128 /* */
129 /*+ Utility : UTIL */
130 /*+ Created : 07-Jul-2000 */
131 /* */
132 /*1- C Procedure ***********+******************************************/
133 INTS4 f_ut_compr_zeros(INTU1 *pc_input,INTS4 l_inlen)
134 {
135 INTU4 I;
136 INTU4 l_bytes;
137 INTU1 *pc_in;
138 
139 pc_in =pc_input;
140 l_bytes=0;
141 for(I=1;I<=l_inlen;I++) if(*pc_in++ == 0) l_bytes++;
142 return (l_bytes*100/l_inlen);
143 }
144 
145 /*1+ C Procedure ***********+******************************************/
146 /* */
147 /*+ Module : f_ut_compr_pack */
148 /* */
149 /*--------------------------------------------------------------------*/
150 /*+ CALLING : size=f_ut_compr_pack(*input,inlen,*output,outlen) */
151 /*--------------------------------------------------------------------*/
152 /* */
153 /*+ PURPOSE : Compress data field by removing zero bytes */
154 /* */
155 /*+ ARGUMENTS : */
156 /* */
157 /*+ input : (INTU1 *) Pointer to input data field. */
158 /*+ inlen : (INTS4) Length of input data field in bytes. */
159 /*+ output : (INTU1 *) Pointer to compressed output data field. */
160 /*+ outlen : (INTS4) Length of output data field. */
161 /* */
162 /*+ Return type : INTS4 */
163 /*+ return : Number of bytes of compressed output */
164 /*+ return : -1: output buffer may be too small */
165 /*+ Include name: f_ut_compress.h */
166 /* */
167 /*2+Description***+***********+****************************************/
168 /* */
169 /*+ CALLING : size=f_ut_compr_pack(*input,inlen,*output,outlen) */
170 /* */
171 /*+ ARGUMENTS : */
172 /* */
173 /*+ input : (INTU1 *) Pointer to input data field. The field */
174 /* must be longword aligned. */
175 /*+ inlen : (INTS4) Length of input data field in bytes. */
176 /*+ output : (INTU1 *) Pointer to output data field. */
177 /* The output field must be 12.5% bigger than input. */
178 /*+ outlen : (INTS4) Length of output data field in bytes. */
179 /* */
180 /*+ FUNCTION : The output field begins with structure s_compress: */
181 /* */
182 /*- INTU4 l_endian: set to 1 by creator */
183 /*- INTU4 l_length: total size [b] of compr. buffer */
184 /*- INTU4 l_masks: # of masks following this header */
185 /*- INTU4 l_full_bytes: # of bytes of uncompressed buffer */
186 /*- INTU4 l_comp_bytes: # of non zero bytes */
187 /*- INTU4 l_pattern: COMPR__PATTERN */
188 /*+ : */
189 /* Then there follow inbytes/32 pattern longwords. */
190 /* Then follow all non zero bytes. */
191 /* Zero bytes are suppressed. The overhead is about */
192 /* 13% of input, i.e. if no zeros are found, output is */
193 /* 13% bigger than input. In the patterns, bits are */
194 /* set for following nonzero bytes, not set for */
195 /* suppressed zero bytes. */
196 /*+ endian : When receiving a compressed buffer one must check */
197 /* the endian. If it is not 1, one must swap */
198 /* s_compress and then s_sompress.l_masks longwords. */
199 /* Then the buffer can be uncompressed. The */
200 /* uncompressed buffer must be checked again for right */
201 /* endian, and eventually swapped. */
202 /* */
203 /*+ EXAMPLE : l=f_ut_compr_pack(pl_data,1024,pl_comp,2000); */
204 /* l=f_ut_compr_unpack(pl_comp,pl_data,1024); */
205 /* pl_data should be the same now. */
206 /* */
207 /*+ NOTE : Output data field must be 13% bigger than input. */
208 /* */
209 /*2+Implementation************+****************************************/
210 /* */
211 /*+ Version : 1.01 */
212 /*+ Author : H.G.Essel */
213 /*+ Last Update : 13-Jul-2000 */
214 /* */
215 /*2+Internals*****+***********+****************************************/
216 /* */
217 /*+ Utility : UTIL */
218 /*+ Created : 07-Jul-2000 */
219 /* */
220 /*1- C Procedure ***********+******************************************/
221 INTS4 f_ut_compr_pack(INTU1 *pc_input,INTS4 l_inlen,INTU1 *pc_output,INTS4 l_outlen)
222 {
223 INTU4 I;
224 INTU4 l_bytes;
225 INTU4 l_mask,l_masks;
226 INTU4 *pl_mask;
227 INTU1 *pc_out,*pc_in,*pc_1;
228 s_compress *ps_compress;
229 
230 /* how many masks do we need: one for 32 bytes */
231 l_masks=(l_inlen >> 5);
232 if(l_inlen%32 != 0) l_masks++;
233 /* on output we need the header, the masks, and maybe all bytes */
234 if(l_outlen < (INTS4) (4*l_masks+sizeof(s_compress)+l_inlen)) return -1;
235 pc_out=pc_output;
236 pc_in =pc_input;
237 ps_compress=(s_compress *)pc_out; /* header */
238 pl_mask=(INTU4 *)(ps_compress+1); /* first mask behind header */
239 pc_out = (INTU1 *)(pl_mask+l_masks);/* first data byte behind all masks */
240 pc_1=pc_out;
241 *pl_mask=0;
242 l_mask=1;
243 l_bytes=0;
244 /* loop over all masks -1 */
245 for(I=1;I<l_masks;I++)
246 {
247  PACK(0x00000001);
248  PACK(0x00000002);
249  PACK(0x00000004);
250  PACK(0x00000008);
251  PACK(0x00000010);
252  PACK(0x00000020);
253  PACK(0x00000040);
254  PACK(0x00000080);
255  PACK(0x00000100);
256  PACK(0x00000200);
257  PACK(0x00000400);
258  PACK(0x00000800);
259  PACK(0x00001000);
260  PACK(0x00002000);
261  PACK(0x00004000);
262  PACK(0x00008000);
263  PACK(0x00010000);
264  PACK(0x00020000);
265  PACK(0x00040000);
266  PACK(0x00080000);
267  PACK(0x00100000);
268  PACK(0x00200000);
269  PACK(0x00400000);
270  PACK(0x00800000);
271  PACK(0x01000000);
272  PACK(0x02000000);
273  PACK(0x04000000);
274  PACK(0x08000000);
275  PACK(0x10000000);
276  PACK(0x20000000);
277  PACK(0x40000000);
278  PACK(0x80000000);
279  pl_mask++;
280  *pl_mask=0;
281 }
282 l_bytes=pc_out-pc_1 ;
283 /* last mask could be less than 32 bytes */
284 l_mask=1;
285 for(I=0;I<(l_inlen-l_masks*32+32);I++)
286 {
287  if(*pc_in != 0){*pl_mask += l_mask; *pc_out++ = *pc_in; l_bytes++; } l_mask = l_mask << 1; pc_in++;
288 }
289 /* add the number of last fragment bytes */
290 ps_compress->l_endian = 1;
291 ps_compress->l_length = l_bytes+4*l_masks+sizeof(s_compress);
292 ps_compress->l_pattern = COMPR__PATTERN;
293 ps_compress->l_masks = l_masks;
294 ps_compress->l_full_bytes = l_inlen;
295 ps_compress->l_comp_bytes = l_bytes; /* without header and masks */
296 
297 return (l_bytes+4*l_masks+sizeof(s_compress));
298 }
299 
300 /*1+ C Procedure ***********+******************************************/
301 /* */
302 /*+ Module : f_ut_compr_unpack */
303 /* */
304 /*--------------------------------------------------------------------*/
305 /*+ CALLING : size=f_ut_compr_unpack(*input,*output,outlen) */
306 /*--------------------------------------------------------------------*/
307 /* */
308 /*+ PURPOSE : Deompress data field. */
309 /* */
310 /*+ ARGUMENTS : */
311 /* */
312 /*+ input : (INTU1 *) Pointer to compressed data field. */
313 /*+ output : (INTU1 *) Pointer to uncompressed output data field.*/
314 /*+ outlen : (INTS4) Length of output data field. */
315 /* */
316 /*+ Return type : INTS4 */
317 /*+ return : 0 : OK */
318 /*+ return : -1: output buffer may be too small */
319 /*+ Include name: f_ut_compress.h */
320 /* */
321 /*2+Description***************+****************************************/
322 /* Receiving a compressed buffer which could have */
323 /* a different endian, proceed as follows: */
324 /* Receive sizeof(s_compress) bytes and check */
325 /* s_compress.l_endian. If not 1 swap s_compress. */
326 /* Get s_compress.l_length-sizeof(s_compress) bytes. */
327 /* Swap next s_compress.l_masks longwords. */
328 /* Call f_ut_compr_unpack to compress the buffer. */
329 /* The uncompressed buffer must be checked for correct */
330 /* endian again. The method is up to the sender. */
331 /* */
332 /*2+Implementation************+****************************************/
333 /* */
334 /*+ Version : 1.01 */
335 /*+ Author : H.G.Essel */
336 /*+ Last Update : 13-Jul-2000 */
337 /* */
338 /*2+Internals*****+***********+****************************************/
339 /* */
340 /*+ Utility : UTIL */
341 /*+ Created : 07-Jul-2000 */
342 /* */
343 /*1- C Procedure ***********+******************************************/
344 INTS4 f_ut_compr_unpack(INTU1 *pc_input,INTU1 *pc_output,INTS4 l_outlen)
345 {
346 INTU4 L;
347 INTU4 l_mask;
348 INTU4 *pl_mask;
349 INTU1 *pc_out,*pc_in;
350 s_compress *ps_compress;
351 
352 ps_compress=(s_compress *)pc_input;
353 /* is output buffer big enough? */
354 if(ps_compress->l_full_bytes > l_outlen) return -1;
355 
356 #ifdef GSI__VMS
357 pl_out=(INTU4 *) pc_output;
358 pl_tmp=pl_out+(ps_compress->l_full_bytes>>2);
359 while(pl_out != pl_tmp) *pl_out++ = 0;
360 #endif
361 #ifdef GSI__LYNX
362 pl_out=(INTU4 *) pc_output;
363 pl_tmp=pl_out+(ps_compress->l_full_bytes>>2);
364 while(pl_out != pl_tmp) *pl_out++ = 0;
365 #endif
366 #ifdef GSI__AIX
367 memset(pc_output,0,ps_compress->l_full_bytes);
368 #endif
369 
370 pl_mask=(INTU4 *)(ps_compress+1);
371 pc_in = (INTU1 *)(pl_mask+ps_compress->l_masks);
372 pc_out=pc_output;
373 /* all masks -1 */
374 for(L=1;L<ps_compress->l_masks;L++)
375 {
376  l_mask=*pl_mask;
377  UNPACK(0x00000001);
378  UNPACK(0x00000002);
379  UNPACK(0x00000004);
380  UNPACK(0x00000008);
381  UNPACK(0x00000010);
382  UNPACK(0x00000020);
383  UNPACK(0x00000040);
384  UNPACK(0x00000080);
385  UNPACK(0x00000100);
386  UNPACK(0x00000200);
387  UNPACK(0x00000400);
388  UNPACK(0x00000800);
389  UNPACK(0x00001000);
390  UNPACK(0x00002000);
391  UNPACK(0x00004000);
392  UNPACK(0x00008000);
393  UNPACK(0x00010000);
394  UNPACK(0x00020000);
395  UNPACK(0x00040000);
396  UNPACK(0x00080000);
397  UNPACK(0x00100000);
398  UNPACK(0x00200000);
399  UNPACK(0x00400000);
400  UNPACK(0x00800000);
401  UNPACK(0x01000000);
402  UNPACK(0x02000000);
403  UNPACK(0x04000000);
404  UNPACK(0x08000000);
405  UNPACK(0x10000000);
406  UNPACK(0x20000000);
407  UNPACK(0x40000000);
408  UNPACK(0x80000000);
409  pl_mask++;
410 }
411 l_mask=*pl_mask;
412 /* restore bytes of last mask (could be less than 32) */
413 for(L=0;L<ps_compress->l_full_bytes-ps_compress->l_masks*32+32;L++)
414 {
415  if(l_mask%2 != 0) *pc_out++ = *pc_in++; else *pc_out++=0;
416  l_mask = l_mask >> 1;
417 }
418 return 0;
419 }
INTS4 f_ut_compr_size(INTU1 *pc_input, INTS4 l_inlen)
Definition: f_ut_compress.c:79
#define PACK(bit)
Definition: f_ut_compress.c:19
INTU4 l_endian
Definition: f_ut_compress.h:21
unsigned int INTU4
Definition: typedefs.h:29
int INTS4
Definition: typedefs.h:28
INTU4 l_pattern
Definition: f_ut_compress.h:26
INTU4 l_full_bytes
Definition: f_ut_compress.h:24
unsigned char INTU1
Definition: typedefs.h:25
#define COMPR__PATTERN
Definition: f_ut_compress.h:18
INTS4 f_ut_compr_unpack(INTU1 *pc_input, INTU1 *pc_output, INTS4 l_outlen)
INTU4 l_length
Definition: f_ut_compress.h:22
INTS4 f_ut_compr_pack(INTU1 *pc_input, INTS4 l_inlen, INTU1 *pc_output, INTS4 l_outlen)
INTU4 l_comp_bytes
Definition: f_ut_compress.h:25
INTU4 l_masks
Definition: f_ut_compress.h:23
INTS4 f_ut_compr_zeros(INTU1 *pc_input, INTS4 l_inlen)