/** * 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); }
/* * 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 }