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