Skip to content

Instantly share code, notes, and snippets.

@opsec-ee
Last active September 26, 2025 05:16
Show Gist options
  • Select an option

  • Save opsec-ee/fe28a236fae315e6be20f61180fc8be4 to your computer and use it in GitHub Desktop.

Select an option

Save opsec-ee/fe28a236fae315e6be20f61180fc8be4 to your computer and use it in GitHub Desktop.
Polymorphic Dispatch in C with cJSON
// Copyright (c) 2025 H.Overman <opsec.ee@pm.me>
// JSON Polymorphic Dispatch
// Email: opsec.ee@pm.me
//
// Changelog:
// - Handles actual JSON parsing with minimal overhead
// - Maintains polymorphic dispatch for varied data
// - Zero-copy where possible
// - Computed goto for dispatch
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <x86intrin.h>
// Single cache line object
typedef struct __attribute__((aligned(64))) {
double v[7]; // Values extracted from JSON
uint8_t n; // Number of values (1-7)
uint8_t p; // Pattern type (0-3)
uint8_t pad[6]; // Padding to 64 bytes
} Obj;
// Fast JSON number parser - minimal validation
static inline double parse_number(const char **s) {
const char *p = *s;
double val = 0;
int neg = 0;
// Skip whitespace
while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++;
// Handle negative
if (*p == '-') { neg = 1; p++; }
// Parse integer part
while (*p >= '0' && *p <= '9') {
val = val * 10 + (*p - '0');
p++;
}
// Parse decimal
if (*p == '.') {
p++;
double frac = 0.1;
while (*p >= '0' && *p <= '9') {
val += (*p - '0') * frac;
frac *= 0.1;
p++;
}
}
// Handle exponent
if (*p == 'e' || *p == 'E') {
p++;
int exp_neg = 0;
if (*p == '-') { exp_neg = 1; p++; }
else if (*p == '+') p++;
int exp = 0;
while (*p >= '0' && *p <= '9') {
exp = exp * 10 + (*p - '0');
p++;
}
double mult = 1.0;
while (exp--) mult *= 10.0;
val = exp_neg ? val / mult : val * mult;
}
*s = p;
return neg ? -val : val;
}
// Extract all numbers from a JSON object/array
static inline int extract_numbers(const char *json, double *vals, int max) {
int n = 0;
const char *p = json;
while (*p && n < max) {
// Skip to next number
while (*p && !(*p >= '0' && *p <= '9') && *p != '-' && *p != '.') {
// Skip strings
if (*p == '"') {
p++;
while (*p && *p != '"') {
if (*p == '\\') p++;
p++;
}
}
p++;
}
if (*p && (*p >= '0' && *p <= '9' || *p == '-' || *p == '.')) {
vals[n++] = parse_number(&p);
}
}
return n;
}
// Hash function for type string
static inline uint32_t hash32(const char *s, size_t len) {
uint32_t h = 5381;
for (size_t i = 0; i < len; i++) {
h = ((h << 5) + h) + s[i];
}
return h;
}
// Parse JSON file into objects
static Obj* parse_json_minimal(const char *filename, size_t *count) {
// Memory map the file
int fd = open(filename, O_RDONLY);
if (fd < 0) return NULL;
struct stat st;
fstat(fd, &st);
char *data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (data == MAP_FAILED) return NULL;
// Quick count of objects (count '{' characters)
*count = 0;
for (size_t i = 0; i < st.st_size; i++) {
if (data[i] == '{') (*count)++;
}
// Allocate aligned object array
Obj *objs = aligned_alloc(64, (*count) * sizeof(Obj));
memset(objs, 0, (*count) * sizeof(Obj));
// Parse each object
const char *p = data;
size_t obj_idx = 0;
while (*p && obj_idx < *count) {
// Find start of object
while (*p && *p != '{') p++;
if (!*p) break;
const char *obj_start = p;
p++; // Skip '{'
// Find end of object
int depth = 1;
const char *obj_end = p;
while (*obj_end && depth > 0) {
if (*obj_end == '{') depth++;
else if (*obj_end == '}') depth--;
else if (*obj_end == '"') {
obj_end++;
while (*obj_end && *obj_end != '"') {
if (*obj_end == '\\') obj_end++;
obj_end++;
}
}
obj_end++;
}
// Extract type if present
const char *type_start = strstr(obj_start, "\"type\"");
uint32_t type_hash = 0;
if (type_start && type_start < obj_end) {
type_start = strchr(type_start, ':');
if (type_start) {
type_start = strchr(type_start, '"');
if (type_start) {
type_start++;
const char *type_end = strchr(type_start, '"');
if (type_end) {
type_hash = hash32(type_start, type_end - type_start);
}
}
}
}
// Extract numeric values
objs[obj_idx].n = extract_numbers(obj_start, objs[obj_idx].v, 7);
// Determine pattern based on value count and type
if (objs[obj_idx].n <= 0) objs[obj_idx].n = 1; // At least 1 value
objs[obj_idx].p = (objs[obj_idx].n - 1) & 3; // Pattern 0-3
obj_idx++;
p = obj_end;
}
munmap(data, st.st_size);
close(fd);
return objs;
}
int main(int argc, char **argv) {
const char *filename = argc > 1 ? argv[1] : "mixed.json";
size_t iterations = argc > 2 ? atoi(argv[2]) : 10000000;
printf("JSON Polymorphic Dispatch\n");
printf("File: %s\n", filename);
// Parse JSON
size_t count;
Obj *objs = parse_json_minimal(filename, &count);
if (!objs || count == 0) {
printf("Failed to parse JSON\n");
return 1;
}
printf("Loaded %zu objects\n", count);
// Show pattern distribution
int patterns[4] = {0};
for (size_t i = 0; i < count; i++) {
patterns[objs[i].p]++;
}
printf("Patterns: [%d, %d, %d, %d]\n", patterns[0], patterns[1], patterns[2], patterns[3]);
// Warmup
for (size_t i = 0; i < 1000; i++) {
__builtin_prefetch(&objs[i % count], 0, 3);
}
// Labels for computed goto dispatch
static void* dispatch[] = { &&P0, &&P1, &&P2, &&P3 };
// Benchmark
uint64_t start = __rdtsc();
double result = 0;
for (size_t i = 0; i < iterations; i++) {
Obj *o = &objs[i % count];
double x = i * 1.5;
// Prefetch next
__builtin_prefetch(&objs[(i + 8) % count], 0, 1);
// Computed goto dispatch
goto *dispatch[o->p & 3];
P0: // Single value pattern
result = x + o->v[0] * 1000.0;
goto next;
P1: // Two value pattern
result = x * o->v[0] + o->v[1];
goto next;
P2: // Three value pattern
result = (x + o->v[0] - o->v[1]) * o->v[2];
goto next;
P3: // Multi-value pattern
result = x * o->v[0];
for (int j = 1; j < o->n && j < 7; j++) {
result = result * 0.9 + o->v[j];
}
next:
asm volatile("" :: "x"(result));
}
uint64_t cycles = __rdtsc() - start;
printf("\n=== RESULTS ===\n");
printf("Iterations: %zu\n", iterations);
printf("Cycles/dispatch: %.2f\n", (double)cycles / iterations);
printf("Throughput: %.2f M/sec\n", iterations / (cycles / 2.4e9) / 1e6);
free(objs);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment