Ejemplo n.º 1
0
/**
 * mdb_money_to_string
 * @mdb: Handle to open MDB database file
 * @start: Offset of the field within the current page
 *
 * Returns: the allocated string that has received the value.
 */
char *mdb_money_to_string(MdbHandle *mdb, int start)
{
	#define num_bytes 8
	int i;
	int neg=0;
	unsigned char multiplier[MAXPRECISION], temp[MAXPRECISION];
	unsigned char product[MAXPRECISION];
	unsigned char money[num_bytes];

	memset(multiplier,0,MAXPRECISION);
	memset(product,0,MAXPRECISION);
	multiplier[0]=1;
	memcpy(money, mdb->pg_buf + start, num_bytes);

	/* Perform two's complement for negative numbers */
	if (money[7] & 0x80) {
		neg = 1;
		for (i=0;i<num_bytes;i++) {
			money[i] = ~money[i];
		}
		for (i=0; i<num_bytes; i++) {
			money[i] ++;
			if (money[i]!=0) break;
		}
	}

	for (i=0;i<num_bytes;i++) {
		/* product += multiplier * current byte */
		multiply_byte(product, money[i], multiplier);

		/* multiplier = multiplier * 256 */
		memcpy(temp, multiplier, MAXPRECISION);
		memset(multiplier,0,MAXPRECISION);
		multiply_byte(multiplier, 256, temp);
	}
	return array_to_string(product, 4, neg);
}
Ejemplo n.º 2
0
/*
 * money is a special case of numeric really...that why its here
 */
char *
tds_money_to_string(const TDS_MONEY * money, char *s)
{
#ifdef HAVE_INT64
	int frac;
	TDS_INT8 mymoney;
	char *p;

	/* sometimes money it's only 4-byte aligned so always compute 64-bit */
	/* FIXME align money/double/bigint in row to 64-bit */
	mymoney = (((TDS_INT8)(((TDS_INT*)money)[0])) << 32) | ((TDS_UINT*) money)[1];

	p = s;
	if (mymoney < 0) {
		*p++ = '-';
		mymoney = -mymoney;
	}
	mymoney = (mymoney / 50 + 1 ) / 2;
	frac = mymoney % 100;
	mymoney /= 100;
	/* if machine is 64 bit you do not need to split mymoney */
#if SIZEOF_LONG < 8
	if (mymoney >= 1000000000) {
		sprintf(p, "%ld%09ld.%02d", (long)(mymoney / 1000000000), (long)(mymoney % 1000000000), frac);
	} else
#endif
		sprintf(p, "%ld.%02d", (long)mymoney, frac);
	return s;
#else
	unsigned char multiplier[MAXPRECISION], temp[MAXPRECISION];
	unsigned char product[MAXPRECISION];
	const unsigned char *number;
	unsigned char tmpnumber[8];
	int i, num_bytes = 8;
	int pos, neg = 0;

	memset(multiplier, 0, MAXPRECISION);
	memset(product, 0, MAXPRECISION);
	multiplier[0] = 1;

	number = (const unsigned char *) money;

#ifdef WORDS_BIGENDIAN
	/* big endian makes things easy */
	memcpy(tmpnumber, number, 8);
#else
	/*
	 * money is two 32 bit ints and thus is out of order on 
	 * little endian machines. Proof of the superiority of 
	 * big endian design. ;)
	 */
	for (i = 0; i < 4; i++)
		tmpnumber[3 - i] = number[i];
	for (i = 4; i < 8; i++)
		tmpnumber[7 - i + 4] = number[i];
#endif

	if (tmpnumber[0] & 0x80) {
		/* negative number -- preform two's complement */
		neg = 1;
		for (i = 0; i < 8; i++) {
			tmpnumber[i] = ~tmpnumber[i];
		}
		for (i = 7; i >= 0; i--) {
			tmpnumber[i] += 1;
			if (tmpnumber[i] != 0)
				break;
		}
	}
	for (pos = num_bytes - 1; pos >= 0; pos--) {
		multiply_byte(product, tmpnumber[pos], multiplier);

		memcpy(temp, multiplier, MAXPRECISION);
		memset(multiplier, 0, MAXPRECISION);
		multiply_byte(multiplier, 256, temp);
	}
	if (neg) {
		s[0] = '-';
		array_to_string(product, 4, &s[1]);
	} else {
		array_to_string(product, 4, s);
	}

	/* round to two decimal places */
	if (s) {
		sprintf(s, "%.02f", atof(s));
	}

	return s;
#endif
}