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