github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/mpz/inp_raw.c (about)

     1  /* mpz_inp_raw -- read an mpz_t in raw format.
     2  
     3  Copyright 2001, 2002, 2005, 2012, 2016 Free Software Foundation, Inc.
     4  
     5  This file is part of the GNU MP Library.
     6  
     7  The GNU MP Library is free software; you can redistribute it and/or modify
     8  it under the terms of either:
     9  
    10    * the GNU Lesser General Public License as published by the Free
    11      Software Foundation; either version 3 of the License, or (at your
    12      option) any later version.
    13  
    14  or
    15  
    16    * the GNU General Public License as published by the Free Software
    17      Foundation; either version 2 of the License, or (at your option) any
    18      later version.
    19  
    20  or both in parallel, as here.
    21  
    22  The GNU MP Library is distributed in the hope that it will be useful, but
    23  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    24  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    25  for more details.
    26  
    27  You should have received copies of the GNU General Public License and the
    28  GNU Lesser General Public License along with the GNU MP Library.  If not,
    29  see https://www.gnu.org/licenses/.  */
    30  
    31  #include <stdio.h>
    32  #include "gmp.h"
    33  #include "gmp-impl.h"
    34  
    35  
    36  /* NTOH_LIMB_FETCH fetches a limb which is in network byte order (ie. big
    37     endian) and produces a normal host byte order result. */
    38  
    39  #if HAVE_LIMB_BIG_ENDIAN
    40  #define NTOH_LIMB_FETCH(limb, src)  do { (limb) = *(src); } while (0)
    41  #endif
    42  
    43  #if HAVE_LIMB_LITTLE_ENDIAN
    44  #define NTOH_LIMB_FETCH(limb, src)  BSWAP_LIMB_FETCH (limb, src)
    45  #endif
    46  
    47  #ifndef NTOH_LIMB_FETCH
    48  #define NTOH_LIMB_FETCH(limb, src)                              \
    49    do {                                                          \
    50      const unsigned char  *__p = (const unsigned char *) (src);  \
    51      mp_limb_t  __limb;                                          \
    52      int        __i;                                             \
    53      __limb = 0;                                                 \
    54      for (__i = 0; __i < GMP_LIMB_BYTES; __i++)               \
    55        __limb = (__limb << 8) | __p[__i];                        \
    56      (limb) = __limb;                                            \
    57    } while (0)
    58  #endif
    59  
    60  
    61  /* Enhancement: The byte swap loop ought to be safe to vectorize on Cray
    62     etc, but someone who knows what they're doing needs to check it.  */
    63  
    64  size_t
    65  mpz_inp_raw (mpz_ptr x, FILE *fp)
    66  {
    67    unsigned char  csize_bytes[4];
    68    mp_size_t      csize, abs_xsize, i;
    69    size_t         size;
    70    size_t         abs_csize;
    71    char           *cp;
    72    mp_ptr         xp, sp, ep;
    73    mp_limb_t      slimb, elimb;
    74  
    75    if (fp == 0)
    76      fp = stdin;
    77  
    78    /* 4 bytes for size */
    79    if (fread (csize_bytes, sizeof (csize_bytes), 1, fp) != 1)
    80      return 0;
    81  
    82    size = (((size_t) csize_bytes[0] << 24) + ((size_t) csize_bytes[1] << 16) +
    83  	  ((size_t) csize_bytes[2] << 8)  + ((size_t) csize_bytes[3]));
    84  
    85    if (size < 0x80000000u)
    86      csize = size;
    87    else
    88      csize = size - 0x80000000u - 0x80000000u;
    89  
    90    abs_csize = ABS (csize);
    91  
    92    /* round up to a multiple of limbs */
    93    abs_xsize = BITS_TO_LIMBS (abs_csize*8);
    94  
    95    if (abs_xsize != 0)
    96      {
    97        xp = MPZ_NEWALLOC (x, abs_xsize);
    98  
    99        /* Get limb boundaries right in the read, for the benefit of the
   100  	 non-nails case.  */
   101        xp[0] = 0;
   102        cp = (char *) (xp + abs_xsize) - abs_csize;
   103        if (fread (cp, abs_csize, 1, fp) != 1)
   104  	return 0;
   105  
   106        if (GMP_NAIL_BITS == 0)
   107  	{
   108  	  /* Reverse limbs to least significant first, and byte swap.  If
   109  	     abs_xsize is odd then on the last iteration elimb and slimb are
   110  	     the same.  It doesn't seem extra code to handle that case
   111  	     separately, to save an NTOH.  */
   112  	  sp = xp;
   113  	  ep = xp + abs_xsize-1;
   114  	  for (i = 0; i < (abs_xsize+1)/2; i++)
   115  	    {
   116  	      NTOH_LIMB_FETCH (elimb, ep);
   117  	      NTOH_LIMB_FETCH (slimb, sp);
   118  	      *sp++ = elimb;
   119  	      *ep-- = slimb;
   120  	    }
   121  	}
   122        else
   123  	{
   124  	  /* It ought to be possible to do the transformation in-place, but
   125  	     for now it's easier to use an extra temporary area.  */
   126  	  mp_limb_t  byte, limb;
   127  	  int	     bits;
   128  	  mp_size_t  tpos;
   129  	  mp_ptr     tp;
   130  	  TMP_DECL;
   131  
   132  	  TMP_MARK;
   133  	  tp = TMP_ALLOC_LIMBS (abs_xsize);
   134  	  limb = 0;
   135  	  bits = 0;
   136  	  tpos = 0;
   137  	  for (i = abs_csize-1; i >= 0; i--)
   138  	    {
   139  	      byte = (unsigned char) cp[i];
   140  	      limb |= (byte << bits);
   141  	      bits += 8;
   142  	      if (bits >= GMP_NUMB_BITS)
   143  		{
   144  		  ASSERT (tpos < abs_xsize);
   145  		  tp[tpos++] = limb & GMP_NUMB_MASK;
   146  		  bits -= GMP_NUMB_BITS;
   147  		  ASSERT (bits < 8);
   148  		  limb = byte >> (8 - bits);
   149  		}
   150  	    }
   151  	  if (bits != 0)
   152  	    {
   153  	      ASSERT (tpos < abs_xsize);
   154  	      tp[tpos++] = limb;
   155  	    }
   156  	  ASSERT (tpos == abs_xsize);
   157  
   158  	  MPN_COPY (xp, tp, abs_xsize);
   159  	  TMP_FREE;
   160  	}
   161  
   162        /* GMP 1.x mpz_out_raw wrote high zero bytes, strip any high zero
   163  	 limbs resulting from this.  Should be a non-zero value here, but
   164  	 for safety don't assume that. */
   165        MPN_NORMALIZE (xp, abs_xsize);
   166      }
   167  
   168    SIZ(x) = (csize >= 0 ? abs_xsize : -abs_xsize);
   169    return abs_csize + 4;
   170  }