Commit 775eb470 authored by Albert Astals Cid's avatar Albert Astals Cid
Browse files

merged goo dir from xpdf3.02, that was easy :D

parent c9b467da
......@@ -40,6 +40,10 @@ dnl ##### Checks for header files.
AC_PATH_XTRA
AC_HEADER_DIRENT
AC_ARG_ENABLE(exceptions,
[ --enable-exceptions use C++ exceptions],
AC_DEFINE([USE_EXCEPTIONS], [], [Throw exceptions to deal with not enough memory and similar problems]))
dnl ##### Switch over to C++. This will make the checks below a little
dnl ##### bit stricter (requiring function prototypes in include files).
dnl ##### (99% of xpdf is written in C++.)
......
......@@ -18,13 +18,17 @@
#include "FixedPoint.h"
#define ln2 ((FixedPoint)0.69314718)
#define ln2 ((FixedPoint)0.69314718)
FixedPoint FixedPoint::sqrt(FixedPoint x) {
FixedPoint y0, y1, z;
if (x.val <= 0) {
y1.val = 0;
} else {
y1.val = x.val >> 1;
y1.val = x.val == 1 ? 2 : x.val >> 1;
do {
y0.val = y1.val;
z = x / y0;
......@@ -34,10 +38,9 @@ FixedPoint FixedPoint::sqrt(FixedPoint x) {
return y1;
}
//~ this is not very accurate
FixedPoint FixedPoint::pow(FixedPoint x, FixedPoint y) {
FixedPoint t, t2, lnx0, lnx, z0, z;
int d, i;
int d, n, i;
if (y.val <= 0) {
z.val = 0;
......@@ -56,6 +59,8 @@ FixedPoint FixedPoint::pow(FixedPoint x, FixedPoint y) {
lnx.val <<= 1;
t = y * lnx;
// exp(y * ln(x))
n = floor(t / ln2);
t -= ln2 * n;
t2 = t;
d = 1;
i = 1;
......@@ -67,6 +72,11 @@ FixedPoint FixedPoint::pow(FixedPoint x, FixedPoint y) {
++i;
d *= i;
} while (::abs(z.val - z0.val) > 2 && d < (1 << fixptShift));
if (n >= 0) {
z.val <<= n;
} else if (n < 0) {
z.val >>= -n;
}
}
return z;
}
......@@ -92,4 +102,19 @@ int FixedPoint::div(int x, int y) {
#endif
}
GBool FixedPoint::divCheck(FixedPoint x, FixedPoint y, FixedPoint *result) {
#if 1 //~tmp
FixPtInt64 z;
z = ((FixPtInt64)x.val << fixptShift) / y.val;
if ((z == 0 && x != 0) ||
z >= ((FixPtInt64)1 << 31) || z < -((FixPtInt64)1 << 31)) {
return gFalse;
}
result->val = z;
return gTrue;
#else
#endif
}
#endif // USE_FIXEDPOINT
......@@ -21,6 +21,7 @@
#include <stdio.h>
#include <stdlib.h>
#include "gtypes.h"
#define fixptShift 16
#define fixptMaskL ((1 << fixptShift) - 1)
......@@ -135,6 +136,10 @@ public:
static FixedPoint pow(FixedPoint x, FixedPoint y);
// Compute *result = x/y; return false if there is an underflow or
// overflow.
static GBool divCheck(FixedPoint x, FixedPoint y, FixedPoint *result);
private:
static FixedPoint make(int valA) { FixedPoint x; x.val = valA; return x; }
......
......@@ -19,9 +19,61 @@
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include "gtypes.h"
#include <math.h>
#include "gmem.h"
#include "GooString.h"
//------------------------------------------------------------------------
union GooStringFormatArg {
int i;
Guint ui;
long l;
Gulong ul;
double f;
char c;
char *s;
GooString *gs;
};
enum GooStringFormatType {
fmtIntDecimal,
fmtIntHex,
fmtIntOctal,
fmtIntBinary,
fmtUIntDecimal,
fmtUIntHex,
fmtUIntOctal,
fmtUIntBinary,
fmtLongDecimal,
fmtLongHex,
fmtLongOctal,
fmtLongBinary,
fmtULongDecimal,
fmtULongHex,
fmtULongOctal,
fmtULongBinary,
fmtDouble,
fmtDoubleTrim,
fmtChar,
fmtString,
fmtGooString,
fmtSpace
};
static char *formatStrings[] = {
"d", "x", "o", "b", "ud", "ux", "uo", "ub",
"ld", "lx", "lo", "lb", "uld", "ulx", "ulo", "ulb",
"f", "g",
"c",
"s",
"t",
"w",
NULL
};
//------------------------------------------------------------------------
int inline GooString::roundedSize(int len) {
int delta;
if (len <= STR_STATIC_SIZE-1)
......@@ -135,28 +187,29 @@ GooString::GooString(GooString *str1, GooString *str2) {
GooString *GooString::fromInt(int x) {
char buf[24]; // enough space for 64-bit ints plus a little extra
GBool neg;
Guint y;
int i;
char *p;
int len;
formatInt(x, buf, sizeof(buf), gFalse, 0, 10, &p, &len);
return new GooString(p, len);
}
i = 24;
if (x == 0) {
buf[--i] = '0';
} else {
if ((neg = x < 0)) {
y = (Guint)-x;
} else {
y = (Guint)x;
}
while (i > 0 && y > 0) {
buf[--i] = '0' + y % 10;
y /= 10;
}
if (neg && i > 0) {
buf[--i] = '-';
}
}
return new GooString(buf + i, 24 - i);
GooString *GooString::format(char *fmt, ...) {
va_list argList;
GooString *s;
s = new GooString();
va_start(argList, fmt);
s->appendfv(fmt, argList);
va_end(argList);
return s;
}
GooString *GooString::formatv(char *fmt, va_list argList) {
GooString *s;
s = new GooString();
s->appendfv(fmt, argList);
return s;
}
GooString::~GooString() {
......@@ -186,6 +239,351 @@ GooString *GooString::append(const char *str, int lengthA) {
return this;
}
GooString *GooString::appendf(char *fmt, ...) {
va_list argList;
va_start(argList, fmt);
appendfv(fmt, argList);
va_end(argList);
return this;
}
GooString *GooString::appendfv(char *fmt, va_list argList) {
GooStringFormatArg *args;
int argsLen, argsSize;
GooStringFormatArg arg;
int idx, width, prec;
GBool reverseAlign, zeroFill;
GooStringFormatType ft;
char buf[65];
int len, i;
char *p0, *p1, *str;
argsLen = 0;
argsSize = 8;
args = (GooStringFormatArg *)gmallocn(argsSize, sizeof(GooStringFormatArg));
p0 = fmt;
while (*p0) {
if (*p0 == '{') {
++p0;
if (*p0 == '{') {
++p0;
append('{');
} else {
// parse the format string
if (!(*p0 >= '0' && *p0 <= '9')) {
break;
}
idx = *p0 - '0';
for (++p0; *p0 >= '0' && *p0 <= '9'; ++p0) {
idx = 10 * idx + (*p0 - '0');
}
if (*p0 != ':') {
break;
}
++p0;
if (*p0 == '-') {
reverseAlign = gTrue;
++p0;
} else {
reverseAlign = gFalse;
}
width = 0;
zeroFill = *p0 == '0';
for (; *p0 >= '0' && *p0 <= '9'; ++p0) {
width = 10 * width + (*p0 - '0');
}
if (*p0 == '.') {
++p0;
prec = 0;
for (; *p0 >= '0' && *p0 <= '9'; ++p0) {
prec = 10 * prec + (*p0 - '0');
}
} else {
prec = 0;
}
for (ft = (GooStringFormatType)0;
formatStrings[ft];
ft = (GooStringFormatType)(ft + 1)) {
if (!strncmp(p0, formatStrings[ft], strlen(formatStrings[ft]))) {
break;
}
}
if (!formatStrings[ft]) {
break;
}
p0 += strlen(formatStrings[ft]);
if (*p0 != '}') {
break;
}
++p0;
// fetch the argument
if (idx > argsLen) {
break;
}
if (idx == argsLen) {
if (argsLen == argsSize) {
argsSize *= 2;
args = (GooStringFormatArg *)greallocn(args, argsSize,
sizeof(GooStringFormatArg));
}
switch (ft) {
case fmtIntDecimal:
case fmtIntHex:
case fmtIntOctal:
case fmtIntBinary:
case fmtSpace:
args[argsLen].i = va_arg(argList, int);
break;
case fmtUIntDecimal:
case fmtUIntHex:
case fmtUIntOctal:
case fmtUIntBinary:
args[argsLen].ui = va_arg(argList, Guint);
break;
case fmtLongDecimal:
case fmtLongHex:
case fmtLongOctal:
case fmtLongBinary:
args[argsLen].l = va_arg(argList, long);
break;
case fmtULongDecimal:
case fmtULongHex:
case fmtULongOctal:
case fmtULongBinary:
args[argsLen].ul = va_arg(argList, Gulong);
break;
case fmtDouble:
case fmtDoubleTrim:
args[argsLen].f = va_arg(argList, double);
break;
case fmtChar:
args[argsLen].c = (char)va_arg(argList, int);
break;
case fmtString:
args[argsLen].s = va_arg(argList, char *);
break;
case fmtGooString:
args[argsLen].gs = va_arg(argList, GooString *);
break;
}
++argsLen;
}
// format the argument
arg = args[idx];
switch (ft) {
case fmtIntDecimal:
formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
break;
case fmtIntHex:
formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
break;
case fmtIntOctal:
formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
break;
case fmtIntBinary:
formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
break;
case fmtUIntDecimal:
formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 10,
&str, &len);
break;
case fmtUIntHex:
formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 16,
&str, &len);
break;
case fmtUIntOctal:
formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
break;
case fmtUIntBinary:
formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
break;
case fmtLongDecimal:
formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
break;
case fmtLongHex:
formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
break;
case fmtLongOctal:
formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
break;
case fmtLongBinary:
formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
break;
case fmtULongDecimal:
formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 10,
&str, &len);
break;
case fmtULongHex:
formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 16,
&str, &len);
break;
case fmtULongOctal:
formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
break;
case fmtULongBinary:
formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
break;
case fmtDouble:
formatDouble(arg.f, buf, sizeof(buf), prec, gFalse, &str, &len);
break;
case fmtDoubleTrim:
formatDouble(arg.f, buf, sizeof(buf), prec, gTrue, &str, &len);
break;
case fmtChar:
buf[0] = arg.c;
str = buf;
len = 1;
reverseAlign = !reverseAlign;
break;
case fmtString:
str = arg.s;
len = strlen(str);
reverseAlign = !reverseAlign;
break;
case fmtGooString:
str = arg.gs->getCString();
len = arg.gs->getLength();
reverseAlign = !reverseAlign;
break;
case fmtSpace:
str = buf;
len = 0;
width = arg.i;
break;
}
// append the formatted arg, handling width and alignment
if (!reverseAlign && len < width) {
for (i = len; i < width; ++i) {
append(' ');
}
}
append(str, len);
if (reverseAlign && len < width) {
for (i = len; i < width; ++i) {
append(' ');
}
}
}
} else if (*p0 == '}') {
++p0;
if (*p0 == '}') {
++p0;
}
append('}');
} else {
for (p1 = p0 + 1; *p1 && *p1 != '{' && *p1 != '}'; ++p1) ;
append(p0, p1 - p0);
p0 = p1;
}
}
gfree(args);
return this;
}
void GooString::formatInt(long x, char *buf, int bufSize,
GBool zeroFill, int width, int base,
char **p, int *len) {
static char vals[17] = "0123456789abcdef";
GBool neg;
int start, i, j;
i = bufSize;
if ((neg = x < 0)) {
x = -x;
}
start = neg ? 1 : 0;
if (x == 0) {
buf[--i] = '0';
} else {
while (i > start && x) {
buf[--i] = vals[x % base];
x /= base;
}
}
if (zeroFill) {
for (j = bufSize - i; i > start && j < width - start; ++j) {
buf[--i] = '0';
}
}
if (neg) {
buf[--i] = '-';
}
*p = buf + i;
*len = bufSize - i;
}
void GooString::formatUInt(Gulong x, char *buf, int bufSize,
GBool zeroFill, int width, int base,
char **p, int *len) {
static char vals[17] = "0123456789abcdef";
int i, j;
i = bufSize;
if (x == 0) {
buf[--i] = '0';
} else {
while (i > 0 && x) {
buf[--i] = vals[x % base];
x /= base;
}
}
if (zeroFill) {
for (j = bufSize - i; i > 0 && j < width; ++j) {
buf[--i] = '0';
}
}
*p = buf + i;
*len = bufSize - i;
}
void GooString::formatDouble(double x, char *buf, int bufSize, int prec,
GBool trim, char **p, int *len) {
GBool neg, started;
double x2;
int d, i, j;
if ((neg = x < 0)) {
x = -x;
}
x = floor(x * pow(10, prec) + 0.5);
i = bufSize;
started = !trim;
for (j = 0; j < prec && i > 1; ++j) {
x2 = floor(0.1 * (x + 0.5));
d = (int)floor(x - 10 * x2 + 0.5);
if (started || d != 0) {
buf[--i] = '0' + d;
started = gTrue;
}
x = x2;
}
if (i > 1 && started) {
buf[--i] = '.';
}
if (i > 1) {
do {
x2 = floor(0.1 * (x + 0.5));
d = (int)floor(x - 10 * x2 + 0.5);
buf[--i] = '0' + d;
x = x2;
} while (i > 1 && x);
}
if (neg) {
buf[--i] = '-';
}
*p = buf + i;
*len = bufSize - i;
}
GooString *GooString::insert(int i, char c) {
return insert(i, (const char*)&c, 1);
}
......
......@@ -8,13 +8,14 @@
//
//========================================================================
#ifndef GSTRING_H
#define GSTRING_H
#ifndef GooString_H
#define GooString_H
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include <stdarg.h>
#include <stdlib.h> // for NULL
#include "gtypes.h"
......@@ -50,6 +51,30 @@ public:
// Convert an integer to a string.
static GooString *fromInt(int x);
// Create a formatted string. Similar to printf, but without the
// string overflow issues. Formatting elements consist of:
// {<arg>:[<width>][.<precision>]<type>}
// where:
// - <arg> is the argument number (arg 0 is the first argument
// following the format string) -- NB: args must be first used in
// order; they can be reused in any order
// - <width> is the field width -- negative to reverse the alignment;
// starting with a leading zero to zero-fill (for integers)
// - <precision> is the number of digits to the right of the decimal
// point (for floating point numbers)
// - <type> is one of:
// d, x, o, b -- int in decimal, hex, octal, binary
// ud, ux, uo, ub -- unsigned int
// ld, lx, lo, lb, uld, ulx, ulo, ulb -- long, unsigned long
// f, g -- double
// c -- char
// s -- string (char *)
// t -- GooString *
// w -- blank space; arg determines width
// To get literal curly braces, use {{ or }}.
static GooString *format(char *fmt, ...);
static GooString *formatv(char *fmt, va_list argList);
// Destructor.
~GooString();
......@@ -73,6 +98,10 @@ public:
GooString *append(GooString *str);
GooString *append(const char *str, int lengthA=CALC_STRING_LEN);
// Append a formatted string.
GooString *appendf(char *fmt, ...);
GooString *appendfv(char *fmt, va_list argList);