summaryrefslogtreecommitdiffstats
path: root/src/output.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/output.h')
-rw-r--r--src/output.h415
1 files changed, 415 insertions, 0 deletions
diff --git a/src/output.h b/src/output.h
new file mode 100644
index 0000000..ca526de
--- /dev/null
+++ b/src/output.h
@@ -0,0 +1,415 @@
+/*
+ * Copyright (c) 2017-2024 OARC, Inc.
+ * Copyright (c) 2011-2017, IIS - The Internet Foundation in Sweden
+ * All rights reserved.
+ *
+ * This file is part of PacketQ.
+ *
+ * PacketQ is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PacketQ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with PacketQ. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __packetq_output_h
+#define __packetq_output_h
+
+#include <stdio.h>
+#include <stdlib.h>
+
+namespace packetq {
+
+class Output {
+ char m_buffer[0x10000];
+ char m_diglut[0x100][4];
+ int m_len;
+ int m_tot;
+
+public:
+ Output()
+ {
+ for (int i = 0; i < 256; i++)
+ snprintf(m_diglut[i], 4, "%d", i);
+
+ m_len = 0;
+ m_tot = 0;
+ }
+ ~Output()
+ {
+ // print();
+ }
+ void reset() { m_len = 0; }
+ void print()
+ {
+ if (!m_len)
+ return;
+ fwrite(m_buffer, m_len, 1, stdout);
+ m_tot += m_len;
+ m_len = 0;
+ }
+ void flush()
+ {
+ print();
+ fflush(stdout);
+ }
+ inline void add_q_string(const char* p)
+ {
+ m_buffer[m_len++] = '"';
+ add_string_esc_json(p);
+ m_buffer[m_len++] = '"';
+ }
+ inline void add_string_esc_json(const char* p)
+ {
+ static const char lut[] = "0123456789ABCDEF";
+ if (m_len > sizeof(m_buffer) / 2)
+ print();
+ char c;
+ while ((c = *p++)) {
+ if (c == '\\') {
+ m_buffer[m_len++] = '\\';
+ c = '\\';
+ } else if (c == '"') {
+ m_buffer[m_len++] = '\\';
+ } else if (c < 0x20) {
+ m_buffer[m_len++] = '\\';
+ m_buffer[m_len++] = 'u';
+ m_buffer[m_len++] = '0';
+ m_buffer[m_len++] = '0';
+ m_buffer[m_len++] = lut[(c >> 4) & 0xf];
+ m_buffer[m_len++] = lut[c & 0xf];
+ continue;
+ }
+ m_buffer[m_len++] = c;
+ }
+ }
+ inline void add_string_esc_xml(const char* p)
+ {
+ if (m_len > sizeof(m_buffer) / 2)
+ print();
+ char c;
+ while ((c = *p++) > 'A') {
+ m_buffer[m_len++] = c;
+ }
+ if (c == 0)
+ return;
+ p--;
+ while ((c = *p++)) {
+ if (c == '>') {
+ m_buffer[m_len++] = '&';
+ add_string("gt");
+ c = ';';
+ }
+ if (c == '<') {
+ m_buffer[m_len++] = '&';
+ add_string("lt");
+ c = ';';
+ }
+ if (c == '\'') {
+ m_buffer[m_len++] = '&';
+ add_string("apos");
+ c = ';';
+ }
+ if (c == '"') {
+ m_buffer[m_len++] = '&';
+ add_string("quot");
+ c = ';';
+ }
+ m_buffer[m_len++] = c;
+ if (c == '&') {
+ add_string("amp;");
+ }
+ }
+ }
+ inline void check()
+ {
+ if (m_len > sizeof(m_buffer) / 2)
+ print();
+ }
+ inline void add_string(const char* p)
+ {
+ check();
+ char c;
+ while ((c = *p++)) {
+ m_buffer[m_len++] = c;
+ }
+ }
+
+ inline void add_hex_ushort(unsigned short v)
+ {
+ static const char lut[] = "0123456789abcdef";
+ if (v & 0xf000) {
+ m_buffer[m_len++] = lut[v >> 12];
+ m_buffer[m_len++] = lut[(v >> 8) & 0xf];
+ m_buffer[m_len++] = lut[(v >> 4) & 0xf];
+ m_buffer[m_len++] = lut[v & 0xf];
+ return;
+ }
+ if (v & 0xf00) {
+ m_buffer[m_len++] = lut[(v >> 8) & 0xf];
+ m_buffer[m_len++] = lut[(v >> 4) & 0xf];
+ m_buffer[m_len++] = lut[v & 0xf];
+ return;
+ }
+ if (v & 0xf0) {
+ m_buffer[m_len++] = lut[(v >> 4) & 0xf];
+ m_buffer[m_len++] = lut[v & 0xf];
+ return;
+ }
+ m_buffer[m_len++] = lut[v & 0xf];
+ }
+
+ inline void add_attr_ipv6(const char* name, unsigned char* addr)
+ {
+ check();
+ add_string_q(name);
+ m_buffer[m_len++] = '=';
+ m_buffer[m_len++] = '"';
+
+ unsigned short digs[8];
+ unsigned char* p = addr;
+ int longest_run = 0;
+ int longest_p = 9;
+ int cur_run = 0;
+ for (int i = 0; i < 8; i++) {
+ digs[i] = ((unsigned short)(p[0]) << 8) | (unsigned short)(p[1]);
+ if (digs[i] == 0) {
+ cur_run++;
+ if ((cur_run > 1) && (cur_run > longest_run)) {
+ longest_run = cur_run;
+ longest_p = i + 1 - cur_run;
+ }
+ } else
+ cur_run = 0;
+
+ p += 2;
+ }
+
+ for (int i = 0; i < 8; i++) {
+ if (i >= longest_p && i < longest_p + longest_run) {
+ if (i == longest_p) {
+ if (i == 0)
+ m_buffer[m_len++] = ':';
+ m_buffer[m_len++] = ':';
+ }
+ } else {
+ add_hex_ushort(digs[i]);
+ if (i != 7)
+ m_buffer[m_len++] = ':';
+ }
+ }
+
+ m_buffer[m_len++] = '"';
+ m_buffer[m_len++] = ' ';
+ }
+
+ inline void add_attr_ipv4(const char* p, unsigned int i)
+ {
+ check();
+ add_string_q(p);
+ m_buffer[m_len++] = '=';
+ m_buffer[m_len++] = '"';
+ add_string_q(m_diglut[i & 255]);
+ m_buffer[m_len++] = '.';
+ add_string_q(m_diglut[(i >> 8) & 255]);
+ m_buffer[m_len++] = '.';
+ add_string_q(m_diglut[(i >> 16) & 255]);
+ m_buffer[m_len++] = '.';
+ add_string_q(m_diglut[(i >> 24)]);
+ m_buffer[m_len++] = '"';
+ m_buffer[m_len++] = ' ';
+ }
+
+ inline void add_attr_bool(const char* p, bool i)
+ {
+ if (!i)
+ return;
+ check();
+ add_string_q(p);
+ m_buffer[m_len++] = '=';
+ m_buffer[m_len++] = '"';
+ m_buffer[m_len++] = i ? '1' : '0';
+ m_buffer[m_len++] = '"';
+ m_buffer[m_len++] = ' ';
+ }
+
+ inline void add_int(unsigned int i)
+ {
+ check();
+ if (i < 256) {
+ add_string_q(m_diglut[i & 255]);
+ } else {
+ unsigned char d[64];
+
+ unsigned char* cd = d;
+ while (i > 0 && cd < (&d[0] + sizeof(d))) {
+ unsigned int n = i;
+ i = i / 100;
+ n = n - (i * 100);
+ *cd++ = n;
+ }
+ if (cd != d) {
+ unsigned char t = *--cd;
+ add_string_q(m_diglut[t]);
+ }
+ while (cd != d) {
+ unsigned char t = *--cd;
+ if (t >= 10)
+ add_string_q(m_diglut[t]);
+ else {
+ m_buffer[m_len++] = '0';
+ m_buffer[m_len++] = '0' + t;
+ }
+ }
+ }
+ }
+ inline void add_attr_int(const char* p, unsigned int i)
+ {
+ check();
+ if (i == 0)
+ return;
+ add_string_q(p);
+ m_buffer[m_len++] = '=';
+ m_buffer[m_len++] = '"';
+ add_int(i);
+ m_buffer[m_len++] = '"';
+ m_buffer[m_len++] = ' ';
+ }
+
+ inline void add_attr_str(const char* p, const char* t)
+ {
+ add_string(p);
+ m_buffer[m_len++] = '=';
+ m_buffer[m_len++] = '"';
+ add_string_esc_json(t);
+ m_buffer[m_len++] = '"';
+ m_buffer[m_len++] = ' ';
+ }
+
+private:
+ inline void add_string_q(const char* p)
+ {
+ char c;
+ while ((c = *p++)) {
+ m_buffer[m_len++] = c;
+ }
+ }
+};
+
+class Str_conv {
+ char m_buffer[0x10000];
+ char m_diglut[0x100][4];
+ int m_len;
+ int m_tot;
+
+public:
+ Str_conv()
+ {
+ for (int i = 0; i < 256; i++)
+ snprintf(m_diglut[i], 4, "%d", i);
+
+ m_len = 0;
+ m_tot = 0;
+ }
+ ~Str_conv()
+ {
+ // print();
+ }
+ const char* get()
+ {
+ m_buffer[m_len] = 0;
+ return m_buffer;
+ }
+ int get_len() { return m_len; }
+ void reset() { m_len = 0; }
+ inline void add_attr_ipv6(unsigned char* addr)
+ {
+ unsigned short digs[8];
+ unsigned char* p = &addr[14];
+ int longest_run = 0;
+ int longest_p = 9;
+ int cur_run = 0;
+ for (int i = 0; i < 8; i++) {
+ digs[i] = ((unsigned short)(p[1]) << 8) | (unsigned short)(p[0]);
+ if (digs[i] == 0) {
+ cur_run++;
+ if ((cur_run > 1) && (cur_run > longest_run)) {
+ longest_run = cur_run;
+ longest_p = i + 1 - cur_run;
+ }
+ } else
+ cur_run = 0;
+
+ p -= 2;
+ }
+
+ for (int i = 0; i < 8; i++) {
+ if (i >= longest_p && i < longest_p + longest_run) {
+ if (i == longest_p) {
+ if (i == 0)
+ m_buffer[m_len++] = ':';
+ m_buffer[m_len++] = ':';
+ }
+ } else {
+ add_hex_ushort(digs[i]);
+ if (i != 7)
+ m_buffer[m_len++] = ':';
+ }
+ }
+ }
+
+ inline void add_string_q(const char* p)
+ {
+ char c;
+ while ((c = *p++)) {
+ m_buffer[m_len++] = c;
+ }
+ }
+
+ inline void add_attr_ipv4(unsigned int i)
+ {
+ add_string_q(m_diglut[(i >> 24)]);
+ m_buffer[m_len++] = '.';
+ add_string_q(m_diglut[(i >> 16) & 255]);
+ m_buffer[m_len++] = '.';
+ add_string_q(m_diglut[(i >> 8) & 255]);
+ m_buffer[m_len++] = '.';
+ add_string_q(m_diglut[(i >> 0) & 255]);
+ }
+ inline void add_hex_ushort(unsigned short v)
+ {
+ static const char lut[] = "0123456789abcdef";
+ if (v & 0xf000) {
+ m_buffer[m_len++] = lut[v >> 12];
+ m_buffer[m_len++] = lut[(v >> 8) & 0xf];
+ m_buffer[m_len++] = lut[(v >> 4) & 0xf];
+ m_buffer[m_len++] = lut[v & 0xf];
+ return;
+ }
+ if (v & 0xf00) {
+ m_buffer[m_len++] = lut[(v >> 8) & 0xf];
+ m_buffer[m_len++] = lut[(v >> 4) & 0xf];
+ m_buffer[m_len++] = lut[v & 0xf];
+ return;
+ }
+ if (v & 0xf0) {
+ m_buffer[m_len++] = lut[(v >> 4) & 0xf];
+ m_buffer[m_len++] = lut[v & 0xf];
+ return;
+ }
+ m_buffer[m_len++] = lut[v & 0xf];
+ }
+};
+
+extern Output g_output;
+
+} // namespace packetq
+
+#endif // __packetq_output_h