view dowa/dowa.h @ 279:b3b547563ec7

Add Google connector service and agent wiki Implement the C/Seobeo Google Drive and Gmail connector with encrypted OAuth storage, Zenbu authentication, browser testing, AI tool discovery, chunked HTTP decoding, and Bazel coverage. Consolidate repository guidance into progressive wiki documentation and enforce arena-first allocation for new first-party C code. Co-authored-by: Copilot <[email protected]> Copilot-Session: 84c338fd-0939-4bb3-b7f3-1062eb213e5d
author MrJuneJune <me@mrjunejune.com>
date Mon, 17 Aug 2026 22:22:36 -0700
parents 1f9877b637e9
children
line wrap: on
line source

#ifndef DOWA
#define DOWA

#include <stdio.h> // printfs...
#include <string.h> // strdup, strlen, memcmp, memcpy
#include <stdlib.h> // malloc, free, realloc
#include <assert.h> // mostly for TODO
#include <stddef.h> // size_t

#include "dowa_internal.h"

// DLAPI macro for DLL export/import
#ifndef DLAPI
  #ifdef _WIN32
    #ifdef DOWA_EXPORTS
      #define DLAPI __declspec(dllexport)
    #else
      #define DLAPI __declspec(dllimport)
    #endif
  #else
    #define DLAPI extern
  #endif
#endif

#define HASH_KEY_NUMBER 5381
#define ONE_MEGA_BYTE   1048576
#define TRUE  1
#define FALSE 0
#define DOWA_HASH_BUCKET_SIZE 8
#define DOWA_HASH_CACHE_LINE_SIZE 64

#define Dowa_Free(p) do { \
  if (p) {                \
    free(p);              \
    (p) = NULL;           \
  }                       \
} while (0)

typedef unsigned long long   uint64;
typedef long long            int64;
typedef unsigned int         uint32;
typedef int                  int32;
typedef unsigned short       uint16;
typedef short                int16;
typedef unsigned char        uint8;
typedef char                 int8;
typedef char                 boolean;

// --- Arena Allocator --- //
typedef struct {
  char   *buffer;
  size_t  offset;
  size_t  capacity;
} Dowa_Arena;

DLAPI Dowa_Arena *Dowa_Arena_Create(size_t capacity);
DLAPI void       *Dowa_Arena_Allocate(Dowa_Arena *p_arena, size_t size);
DLAPI void       *Dowa_Arena_Allocate_Aligned(Dowa_Arena *p_arena, size_t size, size_t alignment);
DLAPI void        Dowa_Arena_Free(Dowa_Arena *p_arena);
DLAPI void       *Dowa_Arena_Copy(Dowa_Arena *p_arena, const void *p_src, size_t size);
DLAPI void        Dowa_Arena_Reset(Dowa_Arena *p_arena);
DLAPI size_t      Dowa_Arena_Get_Used(Dowa_Arena *p_arena);
DLAPI size_t      Dowa_Arena_Get_Remaining(Dowa_Arena *p_arena);

// --- Array and HashMap --- //

typedef enum {
  DOWA_ALLOCATOR_MALLOC = 0,
  DOWA_ALLOCATOR_ARENA = 1
} Dowa_Allocator_Type;

typedef struct {
  size_t length;
  size_t capacity;
  uint8  allocator_type;
  Dowa_Arena *p_arena;
  void *p_hash;
} Dowa_Array_Header;

typedef struct {
  uint32 hash[DOWA_HASH_BUCKET_SIZE];
  uint32 index[DOWA_HASH_BUCKET_SIZE];
} Dowa_Hash_Bucket;

typedef struct {
  size_t bucket_count;
  size_t item_count;
  size_t tombstone_count;
  uint8  allocator_type;
  Dowa_Arena* p_arena;
  Dowa_Hash_Bucket* p_buckets;
} Dowa_Hash_Index;

#define Dowa_KV(K, V) struct { K key; V value; }

#define dowa__header(a) ((Dowa_Array_Header*)(a) - 1)

// --- Array Macros --- //

#define Dowa_Array_Length(a)   ((a) ? dowa__header(a)->length : 0)
#define Dowa_Array_Capacity(a) ((a) ? dowa__header(a)->capacity : 0)

#define Dowa_Array_Push(a, v) \
  ((a) = dowa__array_grow((a), sizeof(*(a)), 0, NULL), \
   (a)[dowa__header(a)->length++] = (v))

#define Dowa_Array_Push_Arena(a, v, arena) \
  ((a) = dowa__array_grow((a), sizeof(*(a)), 0, (arena)), \
   (a)[dowa__header(a)->length++] = (v))

#define Dowa_Array_Pop(a) ((a)[--dowa__header(a)->length])

#define Dowa_Array_Clear(a) ((a) ? (dowa__header(a)->length = 0) : 0)

#define Dowa_Array_Free(a) ((a) ? (dowa__array_free((a)), (a) = NULL) : 0)

#define Dowa_Array_Reserve(a, n) \
  ((a) = dowa__array_grow((a), sizeof(*(a)), (n), NULL))

#define Dowa_Array_Reserve_Arena(a, n, arena) \
  ((a) = dowa__array_grow((a), sizeof(*(a)), (n), (arena)))

// --- HashMap Macros --- //

#define Dowa_HashMap_Get(m, k) \
  dowa__hashmap_get((m), sizeof(*(m)), (k), strlen(k) + 1)

#define Dowa_HashMap_Get_Ptr(m, k) \
  dowa__hashmap_get_ptr((m), sizeof(*(m)), (k), strlen(k) + 1)

#define Dowa_HashMap_Push(m, k, v) \
  do { \
    (m) = dowa__hashmap_push((m), sizeof(*(m)), (k), strlen(k) + 1, NULL); \
    void *p_kv_temp = dowa__hashmap_get_ptr((m), sizeof(*(m)), (k), strlen(k) + 1); \
    if (p_kv_temp) \
      ((typeof(m))p_kv_temp)->value = (v); \
  } while (0)

#define Dowa_HashMap_Push_Arena(m, k, v, arena) \
  do { \
    (m) = dowa__hashmap_push((m), sizeof(*(m)), (k), strlen(k) + 1, (arena)); \
    void *p_kv_temp = dowa__hashmap_get_ptr((m), sizeof(*(m)), (k), strlen(k) + 1); \
    if (p_kv_temp) \
      ((typeof(m))p_kv_temp)->value = (v); \
  } while (0)

#define Dowa_HashMap_Has_Key(m, k) \
  dowa__hashmap_has_key((m), sizeof(*(m)), (k), strlen(k) + 1)

#define Dowa_HashMap_Delete(m, k) \
  dowa__hashmap_delete((m), sizeof(*(m)), (k), strlen(k) + 1)

#define Dowa_HashMap_Clear(m) dowa__hashmap_clear((m), sizeof(*(m)))

#define Dowa_HashMap_Free(m) ((m) ? (dowa__hashmap_free((m)), (m) = NULL) : 0)

#define Dowa_HashMap_Count(m) dowa__hashmap_count(m)

#define Dowa_HashMap_Get_Binary(m, k, ksize) \
  dowa__hashmap_get((m), sizeof(*(m)), (k), (ksize))

#define Dowa_HashMap_Get_Ptr_Binary(m, k, ksize) \
  dowa__hashmap_get_ptr((m), sizeof(*(m)), (k), (ksize))

#define Dowa_HashMap_Push_Binary(m, k, ksize, v) \
  do { \
    (m) = dowa__hashmap_push((m), sizeof(*(m)), (k), (ksize), NULL); \
    void *p_kv_temp = dowa__hashmap_get_ptr((m), sizeof(*(m)), (k), (ksize)); \
    if (p_kv_temp) \
      ((typeof(m))p_kv_temp)->value = (v); \
  } while (0)

#define Dowa_HashMap_Push_Binary_Arena(m, k, ksize, v, arena) \
  do { \
    (m) = dowa__hashmap_push((m), sizeof(*(m)), (k), (ksize), (arena)); \
    void *p_kv_temp = dowa__hashmap_get_ptr((m), sizeof(*(m)), (k), (ksize)); \
    if (p_kv_temp) \
      ((typeof(m))p_kv_temp)->value = (v); \
  } while (0)

// --- Array Core Functions --- //

DLAPI void *dowa__array_grow(void *p_array, size_t element_size, size_t minimum_capacity, Dowa_Arena* p_arena);
DLAPI void  dowa__array_free(void *p_array);

// --- HashMap Core Functions --- //

DLAPI uint32  dowa__hash_bytes(void *p_key, size_t key_size);
DLAPI void   *dowa__hashmap_get(void *p_map, size_t element_size, void *p_key, size_t key_size);
DLAPI void   *dowa__hashmap_get_ptr(void *p_map, size_t element_size, void *p_key, size_t key_size);
DLAPI void   *dowa__hashmap_push(void *p_map, size_t element_size, void *p_key, size_t key_size, Dowa_Arena* p_arena);
DLAPI boolean dowa__hashmap_has_key(void *p_map, size_t element_size, void *p_key, size_t key_size);
DLAPI void    dowa__hashmap_delete(void *p_map, size_t element_size, void *p_key, size_t key_size);
DLAPI void    dowa__hashmap_clear(void *p_map, size_t element_size);
DLAPI void    dowa__hashmap_free(void *p_map);
DLAPI size_t  dowa__hashmap_count(void *p_map);

// --- String Manipulation --- //

DLAPI char       *Dowa_String_Slice(char *from, size_t start, size_t end, Dowa_Arena *p_arena);
DLAPI char      **Dowa_String_Split(char *from, char *token, int32 from_length, int32 token_length, Dowa_Arena *p_arena);
DLAPI char       *Dowa_String_Copy_Arena(char *from, Dowa_Arena *p_arena);
DLAPI int32       Dowa_String_Pos_Find(const char *p_from, const char *p_value, const size_t from_length, const size_t value_length);
DLAPI char       *Dowa_String_Find(const char *p_from, const char *p_value, const size_t from_length, const size_t value_length);
DLAPI int32       Dowa_String_Pos_Find_Char(const char *p_from, int c, int32 from_length);
DLAPI char       *Dowa_String_Find_Char(const char *p_from, int c, int32 from_length);
DLAPI char       *Dowa_String_UUID(uint32 seed, void *buffer);

// --- JSON --- //
typedef enum {
  DOWA_JSON_NULL,
  DOWA_JSON_BOOL,
  DOWA_JSON_NUMBER,
  DOWA_JSON_STRING,
  DOWA_JSON_ARRAY,
  DOWA_JSON_OBJECT
} Dowa_JSON_Type;

typedef struct Dowa_JSON_Value {
  Dowa_JSON_Type type;
  union {
    boolean bool_val;
    double  num_val;
    char   *str_val;
    struct Dowa_JSON_Value *array_val;  // Dowa array of Dowa_JSON_Value
    void   *object_val;                 // Dowa_JSON_Entry* hashmap
  };
} Dowa_JSON_Value;

typedef Dowa_KV(char*, Dowa_JSON_Value) Dowa_JSON_Entry;

DLAPI Dowa_JSON_Value  Dowa_JSON_Parse(const char *json, int32 length, Dowa_Arena *p_arena);
DLAPI Dowa_JSON_Value *Dowa_JSON_Get(Dowa_JSON_Entry *map, const char *key);
DLAPI char            *Dowa_JSON_Get_String(Dowa_JSON_Entry *map, const char *key);
DLAPI double           Dowa_JSON_Get_Number(Dowa_JSON_Entry *map, const char *key);
DLAPI boolean          Dowa_JSON_Get_Bool(Dowa_JSON_Entry *map, const char *key);
DLAPI char            *Dowa_JSON_Escape_String(
    const char *value,
    size_t length,
    Dowa_Arena *p_arena);

// --- Math --- //
DLAPI uint32      Dowa_Math_Random_Uint32(uint32 seed_number);

#endif