Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/mujs/jsnumber.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 #include "jsi.h" | |
| 2 | |
| 3 #if defined(_MSC_VER) && (_MSC_VER < 1700) /* VS2012 has stdint.h */ | |
| 4 typedef unsigned __int64 uint64_t; | |
| 5 #else | |
| 6 #include <stdint.h> | |
| 7 #endif | |
| 8 | |
| 9 static void jsB_new_Number(js_State *J) | |
| 10 { | |
| 11 js_newnumber(J, js_gettop(J) > 1 ? js_tonumber(J, 1) : 0); | |
| 12 } | |
| 13 | |
| 14 static void jsB_Number(js_State *J) | |
| 15 { | |
| 16 js_pushnumber(J, js_gettop(J) > 1 ? js_tonumber(J, 1) : 0); | |
| 17 } | |
| 18 | |
| 19 static void Np_valueOf(js_State *J) | |
| 20 { | |
| 21 js_Object *self = js_toobject(J, 0); | |
| 22 if (self->type != JS_CNUMBER) js_typeerror(J, "not a number"); | |
| 23 js_pushnumber(J, self->u.number); | |
| 24 } | |
| 25 | |
| 26 static void Np_toString(js_State *J) | |
| 27 { | |
| 28 char buf[100]; | |
| 29 js_Object *self = js_toobject(J, 0); | |
| 30 int radix = js_isundefined(J, 1) ? 10 : js_tointeger(J, 1); | |
| 31 double x = 0; | |
| 32 if (self->type != JS_CNUMBER) | |
| 33 js_typeerror(J, "not a number"); | |
| 34 x = self->u.number; | |
| 35 if (radix == 10) { | |
| 36 js_pushstring(J, jsV_numbertostring(J, buf, x)); | |
| 37 return; | |
| 38 } | |
| 39 if (radix < 2 || radix > 36) | |
| 40 js_rangeerror(J, "invalid radix"); | |
| 41 | |
| 42 /* lame number to string conversion for any radix from 2 to 36 */ | |
| 43 { | |
| 44 static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; | |
| 45 double number = x; | |
| 46 int sign = x < 0; | |
| 47 js_Buffer *sb = NULL; | |
| 48 uint64_t u, limit = ((uint64_t)1<<52); | |
| 49 | |
| 50 int ndigits, exp, point; | |
| 51 | |
| 52 if (number == 0) { js_pushstring(J, "0"); return; } | |
| 53 if (isnan(number)) { js_pushstring(J, "NaN"); return; } | |
| 54 if (isinf(number)) { js_pushstring(J, sign ? "-Infinity" : "Infinity"); return; } | |
| 55 | |
| 56 if (sign) | |
| 57 number = -number; | |
| 58 | |
| 59 /* fit as many digits as we want in an int */ | |
| 60 exp = 0; | |
| 61 while (number * pow(radix, exp) > limit) | |
| 62 --exp; | |
| 63 while (number * pow(radix, exp+1) < limit) | |
| 64 ++exp; | |
| 65 u = number * pow(radix, exp) + 0.5; | |
| 66 | |
| 67 /* trim trailing zeros */ | |
| 68 while (u > 0 && (u % radix) == 0) { | |
| 69 u /= radix; | |
| 70 --exp; | |
| 71 } | |
| 72 | |
| 73 /* serialize digits */ | |
| 74 ndigits = 0; | |
| 75 while (u > 0) { | |
| 76 buf[ndigits++] = digits[u % radix]; | |
| 77 u /= radix; | |
| 78 } | |
| 79 point = ndigits - exp; | |
| 80 | |
| 81 if (js_try(J)) { | |
| 82 js_free(J, sb); | |
| 83 js_throw(J); | |
| 84 } | |
| 85 | |
| 86 if (sign) | |
| 87 js_putc(J, &sb, '-'); | |
| 88 | |
| 89 if (point <= 0) { | |
| 90 js_putc(J, &sb, '0'); | |
| 91 js_putc(J, &sb, '.'); | |
| 92 while (point++ < 0) | |
| 93 js_putc(J, &sb, '0'); | |
| 94 while (ndigits-- > 0) | |
| 95 js_putc(J, &sb, buf[ndigits]); | |
| 96 } else { | |
| 97 while (ndigits-- > 0) { | |
| 98 js_putc(J, &sb, buf[ndigits]); | |
| 99 if (--point == 0 && ndigits > 0) | |
| 100 js_putc(J, &sb, '.'); | |
| 101 } | |
| 102 while (point-- > 0) | |
| 103 js_putc(J, &sb, '0'); | |
| 104 } | |
| 105 | |
| 106 js_putc(J, &sb, 0); | |
| 107 js_pushstring(J, sb->s); | |
| 108 | |
| 109 js_endtry(J); | |
| 110 js_free(J, sb); | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 /* Customized ToString() on a number */ | |
| 115 static void numtostr(js_State *J, const char *fmt, int w, double n) | |
| 116 { | |
| 117 /* buf needs to fit printf("%.20f", 1e20) */ | |
| 118 char buf[50], *e; | |
| 119 sprintf(buf, fmt, w, n); | |
| 120 e = strchr(buf, 'e'); | |
| 121 if (e) { | |
| 122 int exp = atoi(e+1); | |
| 123 sprintf(e, "e%+d", exp); | |
| 124 } | |
| 125 js_pushstring(J, buf); | |
| 126 } | |
| 127 | |
| 128 static void Np_toFixed(js_State *J) | |
| 129 { | |
| 130 js_Object *self = js_toobject(J, 0); | |
| 131 int width = js_tointeger(J, 1); | |
| 132 char buf[32]; | |
| 133 double x; | |
| 134 if (self->type != JS_CNUMBER) js_typeerror(J, "not a number"); | |
| 135 if (width < 0) js_rangeerror(J, "precision %d out of range", width); | |
| 136 if (width > 20) js_rangeerror(J, "precision %d out of range", width); | |
| 137 x = self->u.number; | |
| 138 if (isnan(x) || isinf(x) || x <= -1e21 || x >= 1e21) | |
| 139 js_pushstring(J, jsV_numbertostring(J, buf, x)); | |
| 140 else | |
| 141 numtostr(J, "%.*f", width, x); | |
| 142 } | |
| 143 | |
| 144 static void Np_toExponential(js_State *J) | |
| 145 { | |
| 146 js_Object *self = js_toobject(J, 0); | |
| 147 int width = js_tointeger(J, 1); | |
| 148 char buf[32]; | |
| 149 double x; | |
| 150 if (self->type != JS_CNUMBER) js_typeerror(J, "not a number"); | |
| 151 if (width < 0) js_rangeerror(J, "precision %d out of range", width); | |
| 152 if (width > 20) js_rangeerror(J, "precision %d out of range", width); | |
| 153 x = self->u.number; | |
| 154 if (isnan(x) || isinf(x)) | |
| 155 js_pushstring(J, jsV_numbertostring(J, buf, x)); | |
| 156 else | |
| 157 numtostr(J, "%.*e", width, x); | |
| 158 } | |
| 159 | |
| 160 static void Np_toPrecision(js_State *J) | |
| 161 { | |
| 162 js_Object *self = js_toobject(J, 0); | |
| 163 int width = js_tointeger(J, 1); | |
| 164 char buf[32]; | |
| 165 double x; | |
| 166 if (self->type != JS_CNUMBER) js_typeerror(J, "not a number"); | |
| 167 if (width < 1) js_rangeerror(J, "precision %d out of range", width); | |
| 168 if (width > 21) js_rangeerror(J, "precision %d out of range", width); | |
| 169 x = self->u.number; | |
| 170 if (isnan(x) || isinf(x)) | |
| 171 js_pushstring(J, jsV_numbertostring(J, buf, x)); | |
| 172 else | |
| 173 numtostr(J, "%.*g", width, x); | |
| 174 } | |
| 175 | |
| 176 void jsB_initnumber(js_State *J) | |
| 177 { | |
| 178 J->Number_prototype->u.number = 0; | |
| 179 | |
| 180 js_pushobject(J, J->Number_prototype); | |
| 181 { | |
| 182 jsB_propf(J, "Number.prototype.valueOf", Np_valueOf, 0); | |
| 183 jsB_propf(J, "Number.prototype.toString", Np_toString, 1); | |
| 184 jsB_propf(J, "Number.prototype.toLocaleString", Np_toString, 0); | |
| 185 jsB_propf(J, "Number.prototype.toFixed", Np_toFixed, 1); | |
| 186 jsB_propf(J, "Number.prototype.toExponential", Np_toExponential, 1); | |
| 187 jsB_propf(J, "Number.prototype.toPrecision", Np_toPrecision, 1); | |
| 188 } | |
| 189 js_newcconstructor(J, jsB_Number, jsB_new_Number, "Number", 0); /* 1 */ | |
| 190 { | |
| 191 jsB_propn(J, "MAX_VALUE", 1.7976931348623157e+308); | |
| 192 jsB_propn(J, "MIN_VALUE", 5e-324); | |
| 193 jsB_propn(J, "NaN", NAN); | |
| 194 jsB_propn(J, "NEGATIVE_INFINITY", -INFINITY); | |
| 195 jsB_propn(J, "POSITIVE_INFINITY", INFINITY); | |
| 196 } | |
| 197 js_defglobal(J, "Number", JS_DONTENUM); | |
| 198 } |
