00001 //--------------------------------------------------------------- 00002 // Go4 Release Package v2.10-5 (build 21005) 00003 // 03-Nov-2005 00004 //--------------------------------------------------------------- 00005 // The GSI Online Offline Object Oriented (Go4) Project 00006 // Experiment Data Processing at DVEE department, GSI 00007 //--------------------------------------------------------------- 00008 // 00009 //Copyright (C) 2000- Gesellschaft f. Schwerionenforschung, GSI 00010 // Planckstr. 1, 64291 Darmstadt, Germany 00011 //Contact: http://go4.gsi.de 00012 //---------------------------------------------------------------- 00013 //This software can be used under the license agreements as stated 00014 //in Go4License.txt file which is part of the distribution. 00015 //---------------------------------------------------------------- 00016 /* type definitions */ 00017 #include "typedefs.h" 00018 #include "f_ut_compress.h" 00019 #include <stdio.h> 00020 00021 #define PACK(bit) if(*pc_in != 0){*pl_mask += bit ; *pc_out++ = *pc_in; } pc_in++; 00022 00023 #ifdef GSI__LINUX 00024 #define UNPACK(bit) if(l_mask & bit ) *pc_out++ = *pc_in++; else *pc_out++ = 0; 00025 #endif 00026 #ifdef GSI__NT 00027 #define UNPACK(bit) if(l_mask & bit ) *pc_out++ = *pc_in++; else *pc_out++ = 0; 00028 #endif 00029 #ifdef GSI__WINNT 00030 #define UNPACK(bit) if(l_mask & bit ) *pc_out++ = *pc_in++; else *pc_out++ = 0; 00031 #endif 00032 #ifdef GSI__VMS 00033 #define UNPACK(bit) if(l_mask & bit ) *pc_out = *pc_in++; pc_out++; 00034 #endif 00035 #ifdef GSI__AIX 00036 #define UNPACK(bit) if(l_mask & bit ) *pc_out = *pc_in++; pc_out++; 00037 #endif 00038 #ifdef GSI__LYNX 00039 #define UNPACK(bit) if(l_mask & bit ) *pc_out = *pc_in++; pc_out++; 00040 #endif 00041 /*****************+***********+****************************************/ 00042 /* */ 00043 /* GSI, Gesellschaft fuer Schwerionenforschung mbH */ 00044 /* Postfach 11 05 41 */ 00045 /* D-6100 Darmstadt 11 */ 00046 /* */ 00047 /*1+ C Procedure ***********+******************************************/ 00048 /* */ 00049 /*+ Module : f_ut_compr_size */ 00050 /* */ 00051 /*--------------------------------------------------------------------*/ 00052 /*+ CALLING : size=f_ut_compr_size(*input,inlen) */ 00053 /*--------------------------------------------------------------------*/ 00054 /* */ 00055 /*+ PURPOSE : return size of compressed data field. */ 00056 /* */ 00057 /*+ ARGUMENTS : */ 00058 /* */ 00059 /*+ input : (INTU1 *) Pointer to data field. */ 00060 /*+ inlen : (INTS4) Length of input data field [bytes]. */ 00061 /* */ 00062 /*+ Return type : INTS4 */ 00063 /*+ return : Number of bytes of compressed output */ 00064 /*+ Include name: f_ut_compress.h */ 00065 /* */ 00066 /*2+Implementation************+****************************************/ 00067 /* */ 00068 /*+ Version : 1.01 */ 00069 /*+ Author : H.G.Essel */ 00070 /*+ Last Update : 13-Jul-2000 */ 00071 /* */ 00072 /*2+Internals*****+***********+****************************************/ 00073 /* */ 00074 /*+ Utility : UTIL */ 00075 /*+ Created : 07-Jul-2000 */ 00076 /* */ 00077 /*1- C Procedure ***********+******************************************/ 00078 INTS4 f_ut_compr_size(INTU1 *pc_input,INTS4 l_inlen) 00079 { 00080 INTU4 I,J,K,L,M,N; 00081 INTU4 l_bytes; 00082 INTU4 l_masks; 00083 INTU4 *pl_mask,*pl_end; 00084 INTU1 *pc_out,*pc_in; 00085 s_compress *ps_compress; 00086 00087 pc_in =pc_input; 00088 l_bytes=0; 00089 pl_mask=(INTU4 *)pc_input; 00090 pl_end=pl_mask+l_inlen/4; 00091 while(pl_mask!=pl_end) 00092 { 00093 if(*pl_mask&0x000000ff) l_bytes++; 00094 if(*pl_mask&0x0000ff00) l_bytes++; 00095 if(*pl_mask&0x00ff0000) l_bytes++; 00096 if(*pl_mask&0xff000000) l_bytes++; 00097 pl_mask++; 00098 } 00099 if(l_bytes%4 != 0) l_bytes=l_bytes+4-l_bytes%4; 00100 l_masks=(l_inlen >> 5); 00101 if(l_inlen%32 != 0) l_masks++; 00102 return(l_bytes+4*l_masks+sizeof(s_compress)); 00103 } 00104 00105 /*1+ C Procedure ***********+******************************************/ 00106 /* */ 00107 /*+ Module : f_ut_compr_zeros */ 00108 /* */ 00109 /*--------------------------------------------------------------------*/ 00110 /*+ CALLING : zeros=f_ut_compr_zeros(*input,inlen) */ 00111 /*--------------------------------------------------------------------*/ 00112 /* */ 00113 /*+ PURPOSE : return % zero bytes. */ 00114 /* */ 00115 /*+ ARGUMENTS : */ 00116 /* */ 00117 /*+ input : (INTU1 *) Pointer to data field. */ 00118 /*+ inlen : (INTS4) Length of input data field [bytes]. */ 00119 /* */ 00120 /*+ Return type : INTS4 */ 00121 /*+ return : % of zero bytes */ 00122 /*+ Include name: f_ut_compress.h */ 00123 /* */ 00124 /*2+Implementation************+****************************************/ 00125 /* */ 00126 /*+ Version : 1.01 */ 00127 /*+ Author : H.G.Essel */ 00128 /*+ Last Update : 13-Jul-2000 */ 00129 /* */ 00130 /*2+Internals*****+***********+****************************************/ 00131 /* */ 00132 /*+ Utility : UTIL */ 00133 /*+ Created : 07-Jul-2000 */ 00134 /* */ 00135 /*1- C Procedure ***********+******************************************/ 00136 INTS4 f_ut_compr_zeros(INTU1 *pc_input,INTS4 l_inlen) 00137 { 00138 INTU4 I,J,K,L,M,N; 00139 INTU4 l_bytes; 00140 INTU4 l_mask; 00141 INTU4 *pl_mask; 00142 INTU1 *pc_out,*pc_in; 00143 s_compress *ps_compress; 00144 00145 pc_in =pc_input; 00146 l_bytes=0; 00147 for(I=1;I<=l_inlen;I++) if(*pc_in++ == 0) l_bytes++; 00148 return (l_bytes*100/l_inlen); 00149 } 00150 00151 /*1+ C Procedure ***********+******************************************/ 00152 /* */ 00153 /*+ Module : f_ut_compr_pack */ 00154 /* */ 00155 /*--------------------------------------------------------------------*/ 00156 /*+ CALLING : size=f_ut_compr_pack(*input,inlen,*output,outlen) */ 00157 /*--------------------------------------------------------------------*/ 00158 /* */ 00159 /*+ PURPOSE : Compress data field by removing zero bytes */ 00160 /* */ 00161 /*+ ARGUMENTS : */ 00162 /* */ 00163 /*+ input : (INTU1 *) Pointer to input data field. */ 00164 /*+ inlen : (INTS4) Length of input data field in bytes. */ 00165 /*+ output : (INTU1 *) Pointer to compressed output data field. */ 00166 /*+ outlen : (INTS4) Length of output data field. */ 00167 /* */ 00168 /*+ Return type : INTS4 */ 00169 /*+ return : Number of bytes of compressed output */ 00170 /*+ return : -1: output buffer may be too small */ 00171 /*+ Include name: f_ut_compress.h */ 00172 /* */ 00173 /*2+Description***+***********+****************************************/ 00174 /* */ 00175 /*+ CALLING : size=f_ut_compr_pack(*input,inlen,*output,outlen) */ 00176 /* */ 00177 /*+ ARGUMENTS : */ 00178 /* */ 00179 /*+ input : (INTU1 *) Pointer to input data field. The field */ 00180 /* must be longword aligned. */ 00181 /*+ inlen : (INTS4) Length of input data field in bytes. */ 00182 /*+ output : (INTU1 *) Pointer to output data field. */ 00183 /* The output field must be 12.5% bigger than input. */ 00184 /*+ outlen : (INTS4) Length of output data field in bytes. */ 00185 /* */ 00186 /*+ FUNCTION : The output field begins with structure s_compress: */ 00187 /* */ 00188 /*- INTU4 l_endian: set to 1 by creator */ 00189 /*- INTU4 l_length: total size [b] of compr. buffer */ 00190 /*- INTU4 l_masks: # of masks following this header */ 00191 /*- INTU4 l_full_bytes: # of bytes of uncompressed buffer */ 00192 /*- INTU4 l_comp_bytes: # of non zero bytes */ 00193 /*- INTU4 l_pattern: COMPR__PATTERN */ 00194 /*+ : */ 00195 /* Then there follow inbytes/32 pattern longwords. */ 00196 /* Then follow all non zero bytes. */ 00197 /* Zero bytes are suppressed. The overhead is about */ 00198 /* 13% of input, i.e. if no zeros are found, output is */ 00199 /* 13% bigger than input. In the patterns, bits are */ 00200 /* set for following nonzero bytes, not set for */ 00201 /* suppressed zero bytes. */ 00202 /*+ endian : When receiving a compressed buffer one must check */ 00203 /* the endian. If it is not 1, one must swap */ 00204 /* s_compress and then s_sompress.l_masks longwords. */ 00205 /* Then the buffer can be uncompressed. The */ 00206 /* uncompressed buffer must be checked again for right */ 00207 /* endian, and eventually swapped. */ 00208 /* */ 00209 /*+ EXAMPLE : l=f_ut_compr_pack(pl_data,1024,pl_comp,2000); */ 00210 /* l=f_ut_compr_unpack(pl_comp,pl_data,1024); */ 00211 /* pl_data should be the same now. */ 00212 /* */ 00213 /*+ NOTE : Output data field must be 13% bigger than input. */ 00214 /* */ 00215 /*2+Implementation************+****************************************/ 00216 /* */ 00217 /*+ Version : 1.01 */ 00218 /*+ Author : H.G.Essel */ 00219 /*+ Last Update : 13-Jul-2000 */ 00220 /* */ 00221 /*2+Internals*****+***********+****************************************/ 00222 /* */ 00223 /*+ Utility : UTIL */ 00224 /*+ Created : 07-Jul-2000 */ 00225 /* */ 00226 /*1- C Procedure ***********+******************************************/ 00227 INTS4 f_ut_compr_pack(INTU1 *pc_input,INTS4 l_inlen,INTU1 *pc_output,INTS4 l_outlen) 00228 { 00229 INTU4 I,J,K,L,M,N; 00230 INTU4 l_bytes; 00231 INTU4 l_mask,l_masks; 00232 INTU4 *pl_mask; 00233 INTU1 *pc_out,*pc_in,*pc_1; 00234 s_compress *ps_compress; 00235 00236 /* how many masks do we need: one for 32 bytes */ 00237 l_masks=(l_inlen >> 5); 00238 if(l_inlen%32 != 0) l_masks++; 00239 /* on output we need the header, the masks, and maybe all bytes */ 00240 if(l_outlen < 4*l_masks+sizeof(s_compress)+l_inlen) return -1; 00241 pc_out=pc_output; 00242 pc_in =pc_input; 00243 ps_compress=(s_compress *)pc_out; /* header */ 00244 pl_mask=(INTU4 *)(ps_compress+1); /* first mask behind header */ 00245 pc_out = (INTU1 *)(pl_mask+l_masks);/* first data byte behind all masks */ 00246 pc_1=pc_out; 00247 *pl_mask=0; 00248 l_mask=1; 00249 l_bytes=0; 00250 /* loop over all masks -1 */ 00251 for(I=1;I<l_masks;I++) 00252 { 00253 PACK(0x00000001); 00254 PACK(0x00000002); 00255 PACK(0x00000004); 00256 PACK(0x00000008); 00257 PACK(0x00000010); 00258 PACK(0x00000020); 00259 PACK(0x00000040); 00260 PACK(0x00000080); 00261 PACK(0x00000100); 00262 PACK(0x00000200); 00263 PACK(0x00000400); 00264 PACK(0x00000800); 00265 PACK(0x00001000); 00266 PACK(0x00002000); 00267 PACK(0x00004000); 00268 PACK(0x00008000); 00269 PACK(0x00010000); 00270 PACK(0x00020000); 00271 PACK(0x00040000); 00272 PACK(0x00080000); 00273 PACK(0x00100000); 00274 PACK(0x00200000); 00275 PACK(0x00400000); 00276 PACK(0x00800000); 00277 PACK(0x01000000); 00278 PACK(0x02000000); 00279 PACK(0x04000000); 00280 PACK(0x08000000); 00281 PACK(0x10000000); 00282 PACK(0x20000000); 00283 PACK(0x40000000); 00284 PACK(0x80000000); 00285 pl_mask++; 00286 *pl_mask=0; 00287 } 00288 l_bytes=pc_out-pc_1 ; 00289 /* last mask could be less than 32 bytes */ 00290 l_mask=1; 00291 for(I=0;I<(l_inlen-l_masks*32+32);I++) 00292 { 00293 if(*pc_in != 0){*pl_mask += l_mask; *pc_out++ = *pc_in; l_bytes++; } l_mask = l_mask << 1; pc_in++; 00294 } 00295 /* add the number of last fragment bytes */ 00296 ps_compress->l_endian = 1; 00297 ps_compress->l_length = l_bytes+4*l_masks+sizeof(s_compress); 00298 ps_compress->l_pattern = COMPR__PATTERN; 00299 ps_compress->l_masks = l_masks; 00300 ps_compress->l_full_bytes = l_inlen; 00301 ps_compress->l_comp_bytes = l_bytes; /* without header and masks */ 00302 00303 return (l_bytes+4*l_masks+sizeof(s_compress)); 00304 } 00305 00306 /*1+ C Procedure ***********+******************************************/ 00307 /* */ 00308 /*+ Module : f_ut_compr_unpack */ 00309 /* */ 00310 /*--------------------------------------------------------------------*/ 00311 /*+ CALLING : size=f_ut_compr_unpack(*input,*output,outlen) */ 00312 /*--------------------------------------------------------------------*/ 00313 /* */ 00314 /*+ PURPOSE : Deompress data field. */ 00315 /* */ 00316 /*+ ARGUMENTS : */ 00317 /* */ 00318 /*+ input : (INTU1 *) Pointer to compressed data field. */ 00319 /*+ output : (INTU1 *) Pointer to uncompressed output data field.*/ 00320 /*+ outlen : (INTS4) Length of output data field. */ 00321 /* */ 00322 /*+ Return type : INTS4 */ 00323 /*+ return : 0 : OK */ 00324 /*+ return : -1: output buffer may be too small */ 00325 /*+ Include name: f_ut_compress.h */ 00326 /* */ 00327 /*2+Description***************+****************************************/ 00328 /* Receiving a compressed buffer which could have */ 00329 /* a different endian, proceed as follows: */ 00330 /* Receive sizeof(s_compress) bytes and check */ 00331 /* s_compress.l_endian. If not 1 swap s_compress. */ 00332 /* Get s_compress.l_length-sizeof(s_compress) bytes. */ 00333 /* Swap next s_compress.l_masks longwords. */ 00334 /* Call f_ut_compr_unpack to compress the buffer. */ 00335 /* The uncompressed buffer must be checked for correct */ 00336 /* endian again. The method is up to the sender. */ 00337 /* */ 00338 /*2+Implementation************+****************************************/ 00339 /* */ 00340 /*+ Version : 1.01 */ 00341 /*+ Author : H.G.Essel */ 00342 /*+ Last Update : 13-Jul-2000 */ 00343 /* */ 00344 /*2+Internals*****+***********+****************************************/ 00345 /* */ 00346 /*+ Utility : UTIL */ 00347 /*+ Created : 07-Jul-2000 */ 00348 /* */ 00349 /*1- C Procedure ***********+******************************************/ 00350 INTS4 f_ut_compr_unpack(INTU1 *pc_input,INTU1 *pc_output,INTS4 l_outlen) 00351 { 00352 INTU4 I,J,K,L,M,N; 00353 INTU4 l_mask; 00354 INTU4 *pl_mask,*pl_tmp,*pl_out; 00355 INTU1 *pc_out,*pc_in; 00356 s_compress *ps_compress; 00357 00358 ps_compress=(s_compress *)pc_input; 00359 /* is output buffer big enough? */ 00360 if(ps_compress->l_full_bytes > l_outlen) return -1; 00361 00362 #ifdef GSI__VMS 00363 pl_out=(INTU4 *) pc_output; 00364 pl_tmp=pl_out+(ps_compress->l_full_bytes>>2); 00365 while(pl_out != pl_tmp) *pl_out++ = 0; 00366 #endif 00367 #ifdef GSI__LYNX 00368 pl_out=(INTU4 *) pc_output; 00369 pl_tmp=pl_out+(ps_compress->l_full_bytes>>2); 00370 while(pl_out != pl_tmp) *pl_out++ = 0; 00371 #endif 00372 #ifdef GSI__AIX 00373 memset(pc_output,0,ps_compress->l_full_bytes); 00374 #endif 00375 00376 pl_mask=(INTU4 *)(ps_compress+1); 00377 pc_in = (INTU1 *)(pl_mask+ps_compress->l_masks); 00378 pc_out=pc_output; 00379 /* all masks -1 */ 00380 for(L=1;L<ps_compress->l_masks;L++) 00381 { 00382 l_mask=*pl_mask; 00383 UNPACK(0x00000001); 00384 UNPACK(0x00000002); 00385 UNPACK(0x00000004); 00386 UNPACK(0x00000008); 00387 UNPACK(0x00000010); 00388 UNPACK(0x00000020); 00389 UNPACK(0x00000040); 00390 UNPACK(0x00000080); 00391 UNPACK(0x00000100); 00392 UNPACK(0x00000200); 00393 UNPACK(0x00000400); 00394 UNPACK(0x00000800); 00395 UNPACK(0x00001000); 00396 UNPACK(0x00002000); 00397 UNPACK(0x00004000); 00398 UNPACK(0x00008000); 00399 UNPACK(0x00010000); 00400 UNPACK(0x00020000); 00401 UNPACK(0x00040000); 00402 UNPACK(0x00080000); 00403 UNPACK(0x00100000); 00404 UNPACK(0x00200000); 00405 UNPACK(0x00400000); 00406 UNPACK(0x00800000); 00407 UNPACK(0x01000000); 00408 UNPACK(0x02000000); 00409 UNPACK(0x04000000); 00410 UNPACK(0x08000000); 00411 UNPACK(0x10000000); 00412 UNPACK(0x20000000); 00413 UNPACK(0x40000000); 00414 UNPACK(0x80000000); 00415 pl_mask++; 00416 } 00417 l_mask=*pl_mask; 00418 /* restore bytes of last mask (could be less than 32) */ 00419 for(L=0;L<ps_compress->l_full_bytes-ps_compress->l_masks*32+32;L++) 00420 { 00421 if(l_mask%2 != 0) *pc_out++ = *pc_in++; else *pc_out++=0; 00422 l_mask = l_mask >> 1; 00423 } 00424 return 0; 00425 } 00426 00427 //----------------------------END OF GO4 SOURCE FILE ---------------------