summaryrefslogtreecommitdiffstats
path: root/src/common.c
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2026-05-22 18:46:02 +0200
committerGravatar Nikias Bassen2026-05-22 18:46:02 +0200
commit9711459dbed7d60bb00c7d2c052623e8489c88e1 (patch)
tree550cceb133bbff047ad5b8d7e0334596b252f7f2 /src/common.c
parent389fab9a07baf3913c4214425e86cca588d559a1 (diff)
downloadlibplist-9711459dbed7d60bb00c7d2c052623e8489c88e1.tar.gz
libplist-9711459dbed7d60bb00c7d2c052623e8489c88e1.tar.bz2
refactor: centralize formatting helpers and harden out-plutil
Diffstat (limited to 'src/common.c')
-rw-r--r--src/common.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/src/common.c b/src/common.c
new file mode 100644
index 0000000..0b11d57
--- /dev/null
+++ b/src/common.c
@@ -0,0 +1,100 @@
+/*
+ * common.c
+ * contains some common functions
+ *
+ * Copyright (c) 2026 Nikias Bassen, All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <math.h>
+#include <stdio.h>
+#include <stdint.h>
+#include "common.h"
+
+size_t dtostr(char *buf, size_t bufsize, double realval)
+{
+ int slen = 0;
+ if (isnan(realval)) {
+ slen = snprintf(buf, bufsize, "nan");
+ } else if (isinf(realval)) {
+ slen = snprintf(buf, bufsize, "%cinfinity", (realval > 0.0) ? '+' : '-');
+ } else if (realval == 0.0f) {
+ slen = snprintf(buf, bufsize, "0.0");
+ } else {
+ slen = snprintf(buf, bufsize, "%.*g", 17, realval);
+ if (slen < 0) {
+ return 0;
+ }
+ if (!buf || bufsize == 0) {
+ return (size_t)slen;
+ }
+ size_t len = (size_t)slen;
+ if (len >= bufsize) {
+ len = bufsize - 1;
+ }
+ size_t i = 0;
+ for (i = 0; i < len; i++) {
+ if (buf[i] == ',') {
+ buf[i] = '.';
+ break;
+ } else if (buf[i] == '.') {
+ break;
+ }
+ }
+ return len;
+ }
+ if (slen < 0) {
+ return 0;
+ }
+ return (size_t)slen;
+}
+
+/* based on https://stackoverflow.com/a/4143288 */
+#define PO10i_LIMIT (INT64_MAX/10)
+int num_digits_i(int64_t i)
+{
+ int n;
+ int64_t po10;
+ n=1;
+ if (i < 0) {
+ i = (i == INT64_MIN) ? INT64_MAX : -i;
+ n++;
+ }
+ po10=10;
+ while (i>=po10) {
+ n++;
+ if (po10 > PO10i_LIMIT) break;
+ po10*=10;
+ }
+ return n;
+}
+#undef PO10i_LIMIT
+
+/* based on https://stackoverflow.com/a/4143288 */
+#define PO10u_LIMIT (UINT64_MAX/10)
+int num_digits_u(uint64_t i)
+{
+ int n;
+ uint64_t po10;
+ n=1;
+ po10=10;
+ while (i>=po10) {
+ n++;
+ if (po10 > PO10u_LIMIT) break;
+ po10*=10;
+ }
+ return n;
+}
+#undef PO10u_LIMIT