RosettaCodeData/Task/History-variables/C/history-variables.c
2026-04-30 12:34:36 -04:00

126 lines
3 KiB
C

#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
//
// high address________
// |________| length
// T *p ---> |___ ____| most recent value
// |____ ___|
// |
// |___ ____
// |_____ __|
// |________| oldest value
// low address
//
static size_t hv__align(void const *p, size_t z) {
return z + ((sizeof(z) - (((size_t)p + z) % sizeof(z))) % sizeof(z));
}
static size_t hvlen(void const *p, size_t z) {
return *(size_t *)((char *)p + hv__align(p, z));
}
static void *hv__malloc(size_t z) {
size_t const m = z + (2 * sizeof(z));
void *const p = malloc(m);
if(p) {
*(size_t *)((char *)p + hv__align(p, z)) = 1;
return p;
}
perror("");
abort();
}
static void *hv__realloc(void *p, size_t z, size_t n) {
size_t const u = hvlen(p, z);
size_t const o = (n > 1) ? n * z : z;
size_t const g = (u > 1) ? u * z : z;
size_t const m = o + (2 * sizeof(z));
void *const b = (char *)p - (g - z);
p = realloc(b, m);
if(p) {
p = (char *)p + (o - z);
*(size_t *)((char *)p + hv__align(p, z)) = n;
return p;
}
perror("");
abort();
}
static void *hvfree(void const *p, size_t z) {
if(p) {
size_t u = hvlen(p, z);
size_t const o = (u > 1) ? u * z : z;
free((char *)p - (o - z));
}
return NULL;
}
static void *hv(void const *p, size_t z) {
return p ? hv__realloc((void *)p, z, hvlen(p, z) + 1) : hv__malloc(z);
}
#define HV__TYPE(T,V) \
T: *(T *)(V = (hv)((V), sizeof(*(V))))
#define hv(V) _Generic(*(V), \
HV__TYPE( char , (V)), \
HV__TYPE( short , (V)), \
HV__TYPE( int , (V)), \
HV__TYPE( long , (V)), \
HV__TYPE( long long, (V)), \
HV__TYPE(unsigned char , (V)), \
HV__TYPE(unsigned short , (V)), \
HV__TYPE(unsigned int , (V)), \
HV__TYPE(unsigned long , (V)), \
HV__TYPE(unsigned long long, (V)), \
HV__TYPE(float , (V)), \
HV__TYPE(double , (V)), \
HV__TYPE(long double , (V)) \
)
static void const *hvundo(void const *p, size_t z) {
return p ? hv__realloc((void *)p, z, hvlen(p, z) - 1) : p;
}
#define hvundo(V) (V = (hvundo)((V), sizeof(*(V))))
#define hvfree(V) (hvfree)((V), sizeof(*(V)))
#define hvlen(V) (hvlen)((V), sizeof(*(V)))
int main(int argc, char **argv) {
char const *c = NULL;
unsigned const *u = NULL;
double const *d = NULL;
hv(c) = '1';
hv(c) = '2';
hv(c) = '3';
hv(u) = 1;
hv(u) = 21;
hvundo(u);
hv(u) = 12;
hv(u) = 123;
hv(d) = 1.23;
hv(d) = 2.31;
hv(d) = 3.12;
printf("current values : '%c', %u, %g", *c, *u, *d);
putchar('\n');
printf("char value history :");
for(size_t n = hvlen(c), i = 0; i < n; i++) {
printf(" [%zu] '%c',", i, c[-i]);
}
putchar('\n');
printf("unsigned value history:");
for(size_t n = hvlen(u), i = 0; i < n; i++) {
printf(" [%zu] %4u,", i, u[-i]);
}
putchar('\n');
printf("double value history :");
for(size_t n = hvlen(d), i = 0; i < n; i++) {
printf(" [%zu] %4g,", i, d[-i]);
}
putchar('\n');
hvfree(c);
hvfree(u);
hvfree(d);
return 0;
}