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