Skip to content

Commit a49830c

Browse files
committed
Add algorithm.h and portability/fixes
Add new opencstl/algorithm.h and include it in the umbrella header; update amalgamate.py to copy the single-header into examples. Fix various portability and correctness issues: change __cstl_va_start to cast beg=(void*)V, widen RNG state to unsigned __int128 and cast return to unsigned long long, improve platform-specific time functions and fopen behavior, and rename version symbols to OPENCSTL_VERSION/opencstl_version. Tidy up main and tests (limit rand ranges, fix printf formats, reorder test calls, remove dead code) and clean test/check.c. Update README platform table and formatting and make a small CMakeLists tweak.
1 parent 1fc4528 commit a49830c

11 files changed

Lines changed: 158 additions & 145 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ cmake_minimum_required(VERSION 3.10)
22
project(OpenCSTL C)
33

44
set(CMAKE_C_STANDARD 11)
5-
set(CMAKE_CXX_COMPILER 17)
5+
66
set(EXE_NAME OpenCSTL)
77
add_executable(${EXE_NAME} main.c)

README.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@
1212
<a href="README.zh.md">中文</a>
1313
</p>
1414

15+
16+
1517
---
1618

19+
20+
1721
## Why OpenCSTL?
1822

1923
- **Single-header** — Just `#include "opencstl.h"` and you're done. No build steps, no linking.
@@ -51,12 +55,11 @@ curl -LO "https://raw.githubusercontent.com/springkim/OpenCSTL/refs/heads/master
5155

5256
| Compiler | Windows | macOS | Linux |
5357
|----------|:-------:|:-----:|:-----:|
54-
| MSVC (cl) || | |
55-
| GNU (gcc) ||||
58+
| MSVC (cl) || | |
59+
| GNU / MinGW64 (gcc) ||||
5660
| LLVM (clang) ||||
57-
| MinGW64 || | |
58-
| Intel (icx-cc) ||||
59-
| Tiny C Compiler (tcc) || | |
61+
| Intel (icx-cc) ||||
62+
| Tiny C Compiler (tcc) ||||
6063

6164
## Document
6265

@@ -144,6 +147,7 @@ int main() {
144147
```
145148
146149
**Output:**
150+
147151
```
148152
[ 38][ 26][ 13][ 83][ 19][777][ 95][ 78][999][999][999][ 87][ 80][ 86]
149153
[ 13][ 19][ 26][ 38][ 78][ 80][ 83][ 86][ 87][ 95][777][999][999][999]

amalgamate.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import argparse
1919
from pathlib import Path
2020
import shutil
21+
import os
2122

2223
# ──────────────────────────────────────────────────────────────────────────────
2324
# Regex helpers
@@ -248,6 +249,8 @@ def main():
248249
print(f'[amalgamate] done : {len(amalg.visited)} file(s) inlined, '
249250
f'{total} lines → {out_path.name}')
250251

252+
shutil.copy("opencstl.h", "examples/opencstl.h")
253+
251254

252255
if __name__ == '__main__':
253256
main()

main.c

Lines changed: 9 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,14 @@ void cstl_vector_test3() {
8787
DECORATE("opencstl{vector/qsort} test begin");
8888
VECTOR(int) vec = new_vector(int);
8989
for (int i = 0; i < 100; i++) {
90-
int val = rand32();
90+
int val = rand32() % 1000;
9191
push_back(vec, val);
9292
}
9393

9494

9595
stable_sort(vec,size(vec), sizeof(int), LESS(int));
9696
for (int i = 0; i < size(vec); i++) {
97-
printf("Sorted: [%lld]\n", vec[i]);
97+
printf("Sorted: [%d]\n", vec[i]);
9898
}
9999

100100

@@ -371,78 +371,26 @@ void test01() {
371371

372372
void test02() {
373373
VECTOR(int) v = new_vector(int);
374-
for (int i = 0; i < 1000; i++) {
375-
push_back(v, rand32()%10000);
374+
for (int i = 0; i < 100; i++) {
375+
push_back(v, rand32() % 1000);
376376
}
377377

378378
sort(v,size(v), sizeof(int),GREATER(int));
379379

380380

381381
for (int i = 0; i < size(v); i++) {
382-
printf("%d\n", v[i]);
382+
printf("[%4d]\n", v[i]);
383383
}
384384

385-
exit(0);
386-
}
387-
388-
#include <stdio.h>
389-
390-
const char *get_c_version(void) {
391-
#if defined(__STDC_VERSION__)
392-
# if __STDC_VERSION__ >= 202311L
393-
return "C23";
394-
# elif __STDC_VERSION__ >= 201710L
395-
return "C17 (C18)";
396-
# elif __STDC_VERSION__ >= 201112L
397-
return "C11";
398-
# elif __STDC_VERSION__ >= 199901L
399-
return "C99";
400-
# else
401-
return "C94 (AMD1)";
402-
# endif
403-
#elif defined(__STDC__)
404-
return "C89 (C90)";
405-
#else
406-
return "pre-ANSI C (K&R)";
407-
#endif
408-
}
385+
printf("%s\n", opencstl_version());
409386

410-
void print_c_version(void) {
411-
printf("C Standard : %s\n", get_c_version());
412-
413-
#if defined(__STDC_VERSION__)
414-
printf("__STDC_VERSION__ : %ldL\n", (long) __STDC_VERSION__);
415-
#endif
416-
417-
// compiler
418-
#if defined(_MSC_VER)
419-
printf("Compiler : MSVC %d\n", _MSC_VER);
420-
#elif defined(__clang__)
421-
printf("Compiler : Clang %d.%d.%d\n", __clang_major__, __clang_minor__, __clang_patchlevel__);
422-
#elif defined(__GNUC__)
423-
printf("Compiler : GCC %d.%d.%d\n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
424-
#else
425-
printf("Compiler : Unknown\n");
426-
#endif
427-
428-
// platform
429-
#if defined(_WIN32)
430-
printf("Platform : Windows\n");
431-
#elif defined(__APPLE__)
432-
printf("Platform : macOS\n");
433-
#elif defined(__linux__)
434-
printf("Platform : Linux\n");
435-
#else
436-
printf("Platform : Unknown\n");
437-
#endif
387+
exit(0);
438388
}
439389

440390

441391
int main() {
442-
//test02();
443-
//cstl_set_test();
444-
//print_c_version();
445-
test01();
392+
test02();
393+
test01();
446394
//cstl_priority_queue_test();
447395
return 0;
448396
}

opencstl.h

Lines changed: 74 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@
184184
#if defined(_WIN32) || defined(_WIN64) || defined(__TINYC__)
185185
// On Windows the dispatch macros pass values directly (not pointer-to-value).
186186
// va_arg(vl,void*) would read the value itself, so use PTR arithmetic instead.
187-
#define __cstl_va_start(V,C,beg) va_start(V,C);beg=V;
187+
#define __cstl_va_start(V,C,beg) va_start(V,C);beg=(void*)V;
188188
#define __cstl_va_arg(PTR) (PTR)
189189
// Windows: __cstl_va_arg_next is unused (Windows uses PTR-based path),
190190
// but define it to avoid compile errors if referenced.
@@ -3135,6 +3135,31 @@ OPENCSTL_FUNC void __cstl_hashtable_free(void **container) {
31353135
/* ////////////////////////////////////////////////////////////////////////////// */
31363136

31373137

3138+
/* ////////////////////////////////////////////////////////////////////////////// */
3139+
/* BEGIN algorithm.h (depth 1) */
3140+
/* ////////////////////////////////////////////////////////////////////////////// */
3141+
3142+
//
3143+
// Created by spring on 2026. 4. 9..
3144+
//
3145+
3146+
#if !defined(_OPENCSTL_C_ALGORITHM_H)
3147+
#define _OPENCSTL_C_ALGORITHM_H
3148+
#ifndef MAX
3149+
#define MAX(a,b) ((a)>(b)?(a):(b))
3150+
#endif
3151+
#ifndef MIN
3152+
#define MIN(a,b) ((a)<(b)?(a):(b))
3153+
#endif
3154+
3155+
3156+
#endif //_OPENCSTL_C_ALGORITHM_H
3157+
3158+
/* ////////////////////////////////////////////////////////////////////////////// */
3159+
/* END algorithm.h */
3160+
/* ////////////////////////////////////////////////////////////////////////////// */
3161+
3162+
31383163
/* ////////////////////////////////////////////////////////////////////////////// */
31393164
/* BEGIN cstl_compare.h (depth 1) */
31403165
/* ////////////////////////////////////////////////////////////////////////////// */
@@ -3344,8 +3369,11 @@ CompareFunc CSTL_GREATER(const char *type_str) {
33443369
#include <limits.h>
33453370
#define CSTL_RAND64_MAX ULLONG_MAX
33463371
#define CSTL_RAND32_MAX UINT_MAX
3347-
static unsigned long long _seed64 = 1;
3348-
static unsigned long _seed32 = 1;
3372+
static unsigned __int128 _seed64 = 1;
3373+
static unsigned long long _seed32 = 1;
3374+
3375+
//static unsigned long long _seed64 = 1;
3376+
//static unsigned int _seed32 = 1;
33493377

33503378
static void cstl_rand_seed32(unsigned int seed) {
33513379
_seed32 = seed;
@@ -3362,7 +3390,7 @@ static void cstl_rand_seed64(unsigned long long seed) {
33623390

33633391
static unsigned long long cstl_rand64() {
33643392
_seed64 = (_seed64 * 6364136223846793005ULL) + 1442695040888963407ULL;
3365-
return _seed64;
3393+
return (unsigned long long) _seed64;
33663394
}
33673395

33683396

@@ -3383,8 +3411,36 @@ static unsigned long long cstl_rand64() {
33833411
#if !defined(_OPENCSTL_CSTL_TIME_H)
33843412
#define _OPENCSTL_CSTL_TIME_H
33853413

3414+
#if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)
3415+
3416+
#include <windows.h>
3417+
#include <stdio.h>
3418+
3419+
typedef LARGE_INTEGER watch;
3420+
3421+
static watch tick() {
3422+
watch t;
3423+
QueryPerformanceCounter(&t);
3424+
return t;
3425+
}
3426+
3427+
static double lap(const watch t_beg, const watch t_end) {
3428+
LARGE_INTEGER freq;
3429+
QueryPerformanceFrequency(&freq);
3430+
return (double) (t_end.QuadPart - t_beg.QuadPart) * 1000.0 / (double) freq.QuadPart;
3431+
}
3432+
3433+
static void yyyy_mm_dd_hh_mm_ss_ms(char *timestr) {
3434+
SYSTEMTIME st;
3435+
GetLocalTime(&st);
3436+
snprintf(timestr, 32, "%04d_%02d_%02d_%02d_%02d_%02d_%03d",
3437+
(int) st.wYear, (int) st.wMonth, (int) st.wDay,
3438+
(int) st.wHour, (int) st.wMinute, (int) st.wSecond,
3439+
(int) st.wMilliseconds);
3440+
}
3441+
3442+
#elif defined(__MINGW32__) || defined(__MINGW64__) || defined(__GNUC__) || defined(__TINYC__)
33863443

3387-
#if defined(__MINGW32__) || defined(__MINGW64__) || defined(__GNUC__)
33883444
#include <stdio.h>
33893445
#include <sys/time.h>
33903446
#include <time.h>
@@ -3409,66 +3465,23 @@ static void yyyy_mm_dd_hh_mm_ss_ms(char *timestr) {
34093465
time_t now = tv.tv_sec;
34103466
struct tm tm_now;
34113467
#if defined(__MINGW32__) || defined(__MINGW64__)
3412-
localtime_s(&tm_now, &now);
3413-
#elif defined(__clang__) || (defined(__GNUC__) && defined(__APPLE__)) || defined(__GNUC__) | defined(__TINYC__)
3414-
localtime_r(&now, &tm_now);
3468+
localtime_s(&tm_now, &now);
34153469
#else
3416-
localtime_s(&tm_now, &now);
3470+
localtime_r(&now, &tm_now);
34173471
#endif
3418-
int ms = (int) (tv.tv_usec / 1000);
3419-
3420-
snprintf(timestr, 32, "%04d_%02d_%02d_%02d_%02d_%02d_%03d",
3421-
tm_now.tm_year + 1900,
3422-
tm_now.tm_mon + 1,
3423-
tm_now.tm_mday,
3424-
tm_now.tm_hour,
3425-
tm_now.tm_min,
3426-
tm_now.tm_sec,
3427-
ms);
3428-
}
3429-
3430-
#elif defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER) // MSVC, clang-cl
3431-
3432-
#include <windows.h>
3433-
#include <stdio.h>
3434-
3435-
typedef LARGE_INTEGER watch;
34363472

3437-
static watch tick() {
3438-
watch t;
3439-
QueryPerformanceCounter(&t);
3440-
return t;
3441-
}
3442-
3443-
static double lap(const watch t_beg, const watch t_end) {
3444-
LARGE_INTEGER freq;
3445-
QueryPerformanceFrequency(&freq);
3446-
3447-
return (double) (t_end.QuadPart - t_beg.QuadPart) * 1000.0 / (double) freq.QuadPart;
3448-
}
3449-
3450-
static void yyyy_mm_dd_hh_mm_ss_ms(char *timestr) {
3451-
SYSTEMTIME st;
3452-
GetLocalTime(&st);
3453-
3454-
snprintf(timestr, 32, "%04d_%02d_%02d_%02d_%02d_%02d_%03d",
3455-
(int) st.wYear,
3456-
(int) st.wMonth,
3457-
(int) st.wDay,
3458-
(int) st.wHour,
3459-
(int) st.wMinute,
3460-
(int) st.wSecond,
3461-
(int) st.wMilliseconds);
3473+
int ms = (int) (tv.tv_usec / 1000);
3474+
snprintf(timestr, 32, "%04d_%02d_%02d_%02d_%02d_%02d_%03d",
3475+
tm_now.tm_year+ 1900, tm_now.tm_mon+ 1, tm_now.tm_mday,
3476+
tm_now.tm_hour, tm_now.tm_min, tm_now.tm_sec,
3477+
ms);
34623478
}
34633479

34643480
#else
3465-
34663481
#error Unsupported compiler/platform
3467-
34683482
#endif
34693483

3470-
3471-
#endif //_OPENCSTL_CSTL_TIME_H
3484+
#endif
34723485

34733486
/* ////////////////////////////////////////////////////////////////////////////// */
34743487
/* END cstl_time.h */
@@ -3491,14 +3504,10 @@ static void yyyy_mm_dd_hh_mm_ss_ms(char *timestr) {
34913504
bool cstl_fopen(FILE **fp, const char *filename, const char *mode) {
34923505
#if defined(_WIN32) || defined(_WIN64)
34933506
fopen_s(fp, filename, mode);
3494-
#elif defined(__linux__) && defined(__GNUC__)
3495-
*fp = fopen(filename, mode);
3496-
#elif defined(__APPLE__)
3497-
*fp = fopen(filename, mode);
34983507
#else
3499-
fopen_s(fp, filename, mode);
3508+
*fp = fopen(filename, mode);
35003509
#endif
3501-
return fp != NULL;
3510+
return *fp != NULL;
35023511
}
35033512

35043513
bool cstl_getline(FILE *fp, char *line, size_t size) {
@@ -3730,10 +3739,10 @@ static void msort(void *base, size_t nmemb, size_t size, int (*compar)(const voi
37303739
#if !defined(_OPENCSTL_VERSION_H)
37313740
#define _OPENCSTL_VERSION_H
37323741

3733-
static char *VERSION = "1.0.0";
3742+
static char *OPENCSTL_VERSION = "1.0.0";
37343743

3735-
static char *get_version() {
3736-
return VERSION;
3744+
static char *opencstl_version() {
3745+
return OPENCSTL_VERSION;
37373746
}
37383747
#endif //_OPENCSTL_VERSION_H
37393748

opencstl/algorithm.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// Created by spring on 2026. 4. 9..
3+
//
4+
5+
#pragma once
6+
#if !defined(_OPENCSTL_C_ALGORITHM_H)
7+
#define _OPENCSTL_C_ALGORITHM_H
8+
#ifndef MAX
9+
#define MAX(a,b) ((a)>(b)?(a):(b))
10+
#endif
11+
#ifndef MIN
12+
#define MIN(a,b) ((a)<(b)?(a):(b))
13+
#endif
14+
15+
16+
#endif //_OPENCSTL_C_ALGORITHM_H

0 commit comments

Comments
 (0)