github.com/platonnetwork/platon-go@v0.7.6/cases/tool/win/bls_win/include/mcl/conversion.hpp (about)

     1  #pragma once
     2  #include <cybozu/itoa.hpp>
     3  #include <cybozu/stream.hpp>
     4  /**
     5  	@file
     6  	@brief convertion bin/dec/hex <=> array
     7  	@author MITSUNARI Shigeo(@herumi)
     8  	@license modified new BSD license
     9  	http://opensource.org/licenses/BSD-3-Clause
    10  */
    11  #ifdef _MSC_VER
    12  	#pragma warning(push)
    13  	#pragma warning(disable : 4127)
    14  #endif
    15  
    16  namespace mcl { namespace fp {
    17  
    18  namespace local {
    19  
    20  inline bool isSpace(char c)
    21  {
    22  	return c == ' ' || c == '\t' || c == '\r' || c == '\n';
    23  }
    24  template<class InputStream>
    25  bool skipSpace(char *c, InputStream& is)
    26  {
    27  	for (;;) {
    28  		if (!cybozu::readChar(c,  is)) return false;
    29  		if (!isSpace(*c)) return true;
    30  	}
    31  }
    32  
    33  #ifndef CYBOZU_DONT_USE_STRING
    34  template<class InputStream>
    35  void loadWord(std::string& s, InputStream& is)
    36  {
    37  	s.clear();
    38  	char c;
    39  	if (!skipSpace(&c, is)) return;
    40  	s = c;
    41  	for (;;) {
    42  		if (!cybozu::readChar(&c,  is)) return;
    43  		if (isSpace(c)) break;
    44  		s += c;
    45  	}
    46  }
    47  #endif
    48  
    49  template<class InputStream>
    50  size_t loadWord(char *buf, size_t bufSize, InputStream& is)
    51  {
    52  	if (bufSize == 0) return 0;
    53  	char c;
    54  	if (!skipSpace(&c, is)) return 0;
    55  	size_t pos = 0;
    56  	buf[pos++] = c;
    57  	for (;;) {
    58  		if (!cybozu::readChar(&c, is)) break;
    59  		if (isSpace(c)) break;
    60  		if (pos == bufSize) return 0;
    61  		buf[pos++] = c;
    62  	}
    63  	return pos;
    64  }
    65  
    66  
    67  /*
    68  	q = x[] / x
    69  	@retval r = x[] % x
    70  	@note accept q == x
    71  */
    72  inline uint32_t divU32(uint32_t *q, const uint32_t *x, size_t xn, uint32_t y)
    73  {
    74  	if (xn == 0) return 0;
    75  	uint32_t r = 0;
    76  	for (int i = (int)xn - 1; i >= 0; i--) {
    77  		uint64_t t = (uint64_t(r) << 32) | x[i];
    78  		q[i] = uint32_t(t / y);
    79  		r = uint32_t(t % y);
    80  	}
    81  	return r;
    82  }
    83  
    84  /*
    85  	z[0, xn) = x[0, xn) * y
    86  	return z[xn]
    87  	@note accept z == x
    88  */
    89  inline uint32_t mulU32(uint32_t *z, const uint32_t *x, size_t xn, uint32_t y)
    90  {
    91  	uint32_t H = 0;
    92  	for (size_t i = 0; i < xn; i++) {
    93  		uint32_t t = H;
    94  		uint64_t v = uint64_t(x[i]) * y;
    95  		uint32_t L = uint32_t(v);
    96  		H = uint32_t(v >> 32);
    97  		z[i] = t + L;
    98  		if (z[i] < t) {
    99  			H++;
   100  		}
   101  	}
   102  	return H;
   103  }
   104  
   105  /*
   106  	x[0, xn) += y
   107  	return 1 if overflow else 0
   108  */
   109  inline uint32_t addU32(uint32_t *x, size_t xn, uint32_t y)
   110  {
   111  	uint32_t t = x[0] + y;
   112  	x[0] = t;
   113  	if (t >= y) return 0;
   114  	for (size_t i = 1; i < xn; i++) {
   115  		t = x[i] + 1;
   116  		x[i] = t;
   117  		if (t != 0) return 0;
   118  	}
   119  	return 1;
   120  }
   121  
   122  inline uint32_t decToU32(const char *p, size_t size, bool *pb)
   123  {
   124  	assert(0 < size && size <= 9);
   125  	uint32_t x = 0;
   126  	for (size_t i = 0; i < size; i++) {
   127  		char c = p[i];
   128  		if (c < '0' || c > '9') {
   129  			*pb = false;
   130  			return 0;
   131  		}
   132  		x = x * 10 + uint32_t(c - '0');
   133  	}
   134  	*pb = true;
   135  	return x;
   136  }
   137  
   138  inline bool hexCharToUint8(uint8_t *v, char _c)
   139  {
   140  	uint32_t c = uint8_t(_c); // cast is necessary
   141  	if (c - '0' <= '9' - '0') {
   142  		c = c - '0';
   143  	} else if (c - 'a' <= 'f' - 'a') {
   144  		c = (c - 'a') + 10;
   145  	} else if (c - 'A' <= 'F' - 'A') {
   146  		c = (c - 'A') + 10;
   147  	} else {
   148  		return false;
   149  	}
   150  	*v = uint8_t(c);
   151  	return true;
   152  }
   153  
   154  template<class UT>
   155  bool hexToUint(UT *px, const char *p, size_t size)
   156  {
   157  	assert(0 < size && size <= sizeof(UT) * 2);
   158  	UT x = 0;
   159  	for (size_t i = 0; i < size; i++) {
   160  		uint8_t v;
   161  		if (!hexCharToUint8(&v, p[i])) return false;
   162  		x = x * 16 + v;
   163  	}
   164  	*px = x;
   165  	return true;
   166  }
   167  
   168  template<class UT>
   169  bool binToUint(UT *px, const char *p, size_t size)
   170  {
   171  	assert(0 < size && size <= sizeof(UT) * 8);
   172  	UT x = 0;
   173  	for (size_t i = 0; i < size; i++) {
   174  		UT c = static_cast<uint8_t>(p[i]);
   175  		if (c == '0') {
   176  			x = x * 2;
   177  		} else if (c == '1') {
   178  			x = x * 2 + 1;
   179  		} else {
   180  			return false;
   181  		}
   182  	}
   183  	*px = x;
   184  	return true;
   185  }
   186  
   187  inline bool parsePrefix(size_t *readSize, bool *isMinus, int *base, const char *buf, size_t bufSize)
   188  {
   189  	if (bufSize == 0) return false;
   190  	size_t pos = 0;
   191  	if (*buf == '-') {
   192  		if (bufSize == 1) return false;
   193  		*isMinus = true;
   194  		buf++;
   195  		pos++;
   196  	} else {
   197  		*isMinus = false;
   198  	}
   199  	if (buf[0] == '0') {
   200  		if (bufSize > 1 && buf[1] == 'x') {
   201  			if (*base == 0 || *base == 16) {
   202  				*base = 16;
   203  				pos += 2;
   204  			} else {
   205  				return false;
   206  			}
   207  		} else if (bufSize > 1 && buf[1] == 'b') {
   208  			if (*base == 0 || *base == 2) {
   209  				*base = 2;
   210  				pos += 2;
   211  			}
   212  		}
   213  	}
   214  	if (*base == 0) *base = 10;
   215  	if (pos == bufSize) return false;
   216  	*readSize = pos;
   217  	return true;
   218  }
   219  
   220  } // mcl::fp::local
   221  
   222  /*
   223  	convert little endian x[0, xn) to buf
   224  	return written size if success else 0
   225  	data is buf[bufSize - retval, bufSize)
   226  	start "0x" if withPrefix
   227  */
   228  template<class T>
   229  size_t arrayToHex(char *buf, size_t bufSize, const T *x, size_t n, bool withPrefix = false)
   230  {
   231  	size_t fullN = 0;
   232  	if (n > 1) {
   233  		size_t pos = n - 1;
   234  		while (pos > 0) {
   235  			if (x[pos]) break;
   236  			pos--;
   237  		}
   238  		if (pos > 0) fullN = pos;
   239  	}
   240  	const T v = n == 0 ? 0 : x[fullN];
   241  	const size_t topLen = cybozu::getHexLength(v);
   242  	const size_t startPos = withPrefix ? 2 : 0;
   243  	const size_t lenT = sizeof(T) * 2;
   244  	const size_t totalSize = startPos + fullN * lenT + topLen;
   245  	if (totalSize > bufSize) return 0;
   246  	char *const top = buf + bufSize - totalSize;
   247  	if (withPrefix) {
   248  		top[0] = '0';
   249  		top[1] = 'x';
   250  	}
   251  	cybozu::itohex(&top[startPos], topLen, v, false);
   252  	for (size_t i = 0; i < fullN; i++) {
   253  		cybozu::itohex(&top[startPos + topLen + i * lenT], lenT, x[fullN - 1 - i], false);
   254  	}
   255  	return totalSize;
   256  }
   257  
   258  /*
   259  	convert little endian x[0, xn) to buf
   260  	return written size if success else 0
   261  	data is buf[bufSize - retval, bufSize)
   262  	start "0b" if withPrefix
   263  */
   264  template<class T>
   265  size_t arrayToBin(char *buf, size_t bufSize, const T *x, size_t n, bool withPrefix)
   266  {
   267  	size_t fullN = 0;
   268  	if (n > 1) {
   269  		size_t pos = n - 1;
   270  		while (pos > 0) {
   271  			if (x[pos]) break;
   272  			pos--;
   273  		}
   274  		if (pos > 0) fullN = pos;
   275  	}
   276  	const T v = n == 0 ? 0 : x[fullN];
   277  	const size_t topLen = cybozu::getBinLength(v);
   278  	const size_t startPos = withPrefix ? 2 : 0;
   279  	const size_t lenT = sizeof(T) * 8;
   280  	const size_t totalSize = startPos + fullN * lenT + topLen;
   281  	if (totalSize > bufSize) return 0;
   282  	char *const top = buf + bufSize - totalSize;
   283  	if (withPrefix) {
   284  		top[0] = '0';
   285  		top[1] = 'b';
   286  	}
   287  	cybozu::itobin(&top[startPos], topLen, v);
   288  	for (size_t i = 0; i < fullN; i++) {
   289  		cybozu::itobin(&top[startPos + topLen + i * lenT], lenT, x[fullN - 1 - i]);
   290  	}
   291  	return totalSize;
   292  }
   293  
   294  /*
   295  	convert hex string to x[0..xn)
   296  	hex string = [0-9a-fA-F]+
   297  */
   298  template<class UT>
   299  inline size_t hexToArray(UT *x, size_t maxN, const char *buf, size_t bufSize)
   300  {
   301  	if (bufSize == 0) return 0;
   302  	const size_t unitLen = sizeof(UT) * 2;
   303  	const size_t q = bufSize / unitLen;
   304  	const size_t r = bufSize % unitLen;
   305  	const size_t requireSize = q + (r ? 1 : 0);
   306  	if (maxN < requireSize) return 0;
   307  	for (size_t i = 0; i < q; i++) {
   308  		if (!local::hexToUint(&x[i], &buf[r + (q - 1 - i) * unitLen], unitLen)) return 0;
   309  	}
   310  	if (r) {
   311  		if (!local::hexToUint(&x[q], buf, r)) return 0;
   312  	}
   313  	return requireSize;
   314  }
   315  /*
   316  	convert bin string to x[0..xn)
   317  	bin string = [01]+
   318  */
   319  template<class UT>
   320  inline size_t binToArray(UT *x, size_t maxN, const char *buf, size_t bufSize)
   321  {
   322  	if (bufSize == 0) return 0;
   323  	const size_t unitLen = sizeof(UT) * 8;
   324  	const size_t q = bufSize / unitLen;
   325  	const size_t r = bufSize % unitLen;
   326  	const size_t requireSize = q + (r ? 1 : 0);
   327  	if (maxN < requireSize) return 0;
   328  	for (size_t i = 0; i < q; i++) {
   329  		if (!local::binToUint(&x[i], &buf[r + (q - 1 - i) * unitLen], unitLen)) return 0;
   330  	}
   331  	if (r) {
   332  		if (!local::binToUint(&x[q], buf, r)) return 0;
   333  	}
   334  	return requireSize;
   335  }
   336  
   337  /*
   338  	little endian x[0, xn) to buf
   339  	return written size if success else 0
   340  	data is buf[bufSize - retval, bufSize)
   341  */
   342  template<class UT>
   343  inline size_t arrayToDec(char *buf, size_t bufSize, const UT *x, size_t xn)
   344  {
   345  	const size_t maxN = 64;
   346  	uint32_t t[maxN];
   347  	if (sizeof(UT) == 8) {
   348  		xn *= 2;
   349  	}
   350  	if (xn > maxN) return 0;
   351  	memcpy(t, x, xn * sizeof(t[0]));
   352  
   353  	const size_t width = 9;
   354  	const uint32_t i1e9 = 1000000000U;
   355  	size_t pos = 0;
   356  	for (;;) {
   357  		uint32_t r = local::divU32(t, t, xn, i1e9);
   358  		while (xn > 0 && t[xn - 1] == 0) xn--;
   359  		size_t len = cybozu::itoa_local::uintToDec(buf, bufSize - pos, r);
   360  		if (len == 0) return 0;
   361  		assert(0 < len && len <= width);
   362  		if (xn == 0) return pos + len;
   363  		// fill (width - len) '0'
   364  		for (size_t j = 0; j < width - len; j++) {
   365  			buf[bufSize - pos - width + j] = '0';
   366  		}
   367  		pos += width;
   368  	}
   369  }
   370  
   371  /*
   372  	convert buf[0, bufSize) to x[0, num)
   373  	return written num if success else 0
   374  */
   375  template<class UT>
   376  inline size_t decToArray(UT *_x, size_t maxN, const char *buf, size_t bufSize)
   377  {
   378  	assert(sizeof(UT) == 4 || sizeof(UT) == 8);
   379  	const size_t width = 9;
   380  	const uint32_t i1e9 = 1000000000U;
   381  	if (maxN == 0) return 0;
   382  	if (sizeof(UT) == 8) {
   383  		maxN *= 2;
   384  	}
   385  	uint32_t *x = reinterpret_cast<uint32_t*>(_x);
   386  	size_t xn = 1;
   387  	x[0] = 0;
   388  	while (bufSize > 0) {
   389  		size_t n = bufSize % width;
   390  		if (n == 0) n = width;
   391  		bool b;
   392  		uint32_t v = local::decToU32(buf, n, &b);
   393  		if (!b) return 0;
   394  		uint32_t H = local::mulU32(x, x, xn, i1e9);
   395  		if (H > 0) {
   396  			if (xn == maxN) return 0;
   397  			x[xn++] = H;
   398  		}
   399  		H = local::addU32(x, xn, v);
   400  		if (H > 0) {
   401  			if (xn == maxN) return 0;
   402  			x[xn++] = H;
   403  		}
   404  		buf += n;
   405  		bufSize -= n;
   406  	}
   407  	if (sizeof(UT) == 8 && (xn & 1)) {
   408  		x[xn++] = 0;
   409  	}
   410  	return xn / (sizeof(UT) / 4);
   411  }
   412  
   413  /*
   414  	return retavl is written size if success else 0
   415  	REMARK : the top of string is buf + bufSize - retval
   416  */
   417  template<class UT>
   418  size_t arrayToStr(char *buf, size_t bufSize, const UT *x, size_t n, int base, bool withPrefix)
   419  {
   420  	switch (base) {
   421  	case 0:
   422  	case 10:
   423  		return arrayToDec(buf, bufSize, x, n);
   424  	case 16:
   425  		return arrayToHex(buf, bufSize, x, n, withPrefix);
   426  	case 2:
   427  		return arrayToBin(buf, bufSize, x, n, withPrefix);
   428  	default:
   429  		return 0;
   430  	}
   431  }
   432  
   433  template<class UT>
   434  size_t strToArray(bool *pIsMinus, UT *x, size_t xN, const char *buf, size_t bufSize, int ioMode)
   435  {
   436  	ioMode &= 31;
   437  	size_t readSize;
   438  	if (!local::parsePrefix(&readSize, pIsMinus, &ioMode, buf, bufSize)) return 0;
   439  	switch (ioMode) {
   440  	case 10:
   441  		return decToArray(x, xN, buf + readSize, bufSize - readSize);
   442  	case 16:
   443  		return hexToArray(x, xN, buf + readSize, bufSize - readSize);
   444  	case 2:
   445  		return binToArray(x, xN, buf + readSize, bufSize - readSize);
   446  	default:
   447  		return 0;
   448  	}
   449  }
   450  
   451  /*
   452  	convert src[0, n) to (n * 2) byte hex string and write it to os
   453  	return true if success else flase
   454  */
   455  template<class OutputStream>
   456  void writeHexStr(bool *pb, OutputStream& os, const void *src, size_t n)
   457  {
   458  	const uint8_t *p = (const uint8_t *)src;
   459  	for (size_t i = 0; i < n; i++) {
   460  		char hex[2];
   461  		cybozu::itohex(hex, sizeof(hex), p[i], false);
   462  		cybozu::write(pb, os, hex, sizeof(hex));
   463  		if (!*pb) return;
   464  	}
   465  	*pb = true;
   466  }
   467  /*
   468  	read hex string from is and convert it to byte array
   469  	return written buffer size
   470  */
   471  template<class InputStream>
   472  inline size_t readHexStr(void *buf, size_t n, InputStream& is)
   473  {
   474  	bool b;
   475  	uint8_t *dst = (uint8_t *)buf;
   476  	for (size_t i = 0; i < n; i++) {
   477  		uint8_t L, H;
   478  		char c[2];
   479  		if (cybozu::readSome(c, sizeof(c), is) != sizeof(c)) return i;
   480  		b = local::hexCharToUint8(&H, c[0]);
   481  		if (!b) return i;
   482  		b = local::hexCharToUint8(&L, c[1]);
   483  		if (!b) return i;
   484  		dst[i] = (H << 4) | L;
   485  	}
   486  	return n;
   487  }
   488  
   489  } } // mcl::fp
   490  
   491  #ifdef _MSC_VER
   492  	#pragma warning(pop)
   493  #endif