Skip to content

Commit a51c9f0

Browse files
committed
Updated vendored nob.h
1 parent 6cc609f commit a51c9f0

File tree

1 file changed

+150
-6
lines changed

1 file changed

+150
-6
lines changed

nob.h

Lines changed: 150 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* nob - v1.23.0 - Public Domain - https://github.com/tsoding/nob.h
1+
/* nob - v1.25.0 - Public Domain - https://github.com/tsoding/nob.h
22
33
This library is the next generation of the [NoBuild](https://github.com/tsoding/nobuild) idea.
44
@@ -80,6 +80,7 @@
8080
- NOB_EXPERIMENTAL_DELETE_OLD - Experimental feature that automatically removes `nob.old` files. It's unclear how well
8181
it works on Windows, so it's experimental for now.
8282
- NOB_STRIP_PREFIX - string the `nob_` prefixes from non-redefinable names.
83+
- NOB_NO_ECHO - do not echo the actions various nob functions are doing (like nob_cmd_run(), nob_mkdir_if_not_exists(), etc).
8384
8485
## Redefinable Macros
8586
@@ -322,8 +323,21 @@ typedef struct {
322323
size_t capacity;
323324
} Nob_String_Builder;
324325

326+
#define nob_swap(T, a, b) do { T t = a; a = b; b = t; } while (0)
327+
325328
NOBDEF bool nob_read_entire_file(const char *path, Nob_String_Builder *sb);
326329
NOBDEF int nob_sb_appendf(Nob_String_Builder *sb, const char *fmt, ...) NOB_PRINTF_FORMAT(2, 3);
330+
// Pads the String_Builder (sb) to the desired word size boundary with 0s.
331+
// Imagine we have sb that contains 5 `a`-s:
332+
//
333+
// aaaa|a
334+
//
335+
// If we pad align it by size 4 it will look like this:
336+
//
337+
// aaaa|a000| <- padded with 0s to the next size 4 boundary
338+
//
339+
// Useful when you are building some sort of binary format using String_Builder.
340+
NOBDEF void nob_sb_pad_align(Nob_String_Builder *sb, size_t size);
327341

328342
// Append a sized buffer to a string builder
329343
#define nob_sb_append_buf(sb, buf, size) nob_da_append_many(sb, buf, size)
@@ -521,6 +535,7 @@ NOBDEF bool nob_cmd_run_sync_redirect_and_reset(Nob_Cmd *cmd, Nob_Cmd_Redirect r
521535
#define NOB_TEMP_CAPACITY (8*1024*1024)
522536
#endif // NOB_TEMP_CAPACITY
523537
NOBDEF char *nob_temp_strdup(const char *cstr);
538+
NOBDEF char *nob_temp_strndup(const char *cstr, size_t size);
524539
NOBDEF void *nob_temp_alloc(size_t size);
525540
NOBDEF char *nob_temp_sprintf(const char *format, ...) NOB_PRINTF_FORMAT(1, 2);
526541
// nob_temp_reset() - Resets the entire temporary storage to 0.
@@ -557,6 +572,11 @@ NOBDEF int nob_needs_rebuild1(const char *output_path, const char *input_path);
557572
NOBDEF int nob_file_exists(const char *file_path);
558573
NOBDEF const char *nob_get_current_dir_temp(void);
559574
NOBDEF bool nob_set_current_dir(const char *path);
575+
// Returns you the directory part of the path allocated on the temporary storage.
576+
NOBDEF char *nob_temp_dir_name(const char *path);
577+
NOBDEF char *nob_temp_file_name(const char *path);
578+
NOBDEF char *nob_temp_file_ext(const char *path);
579+
NOBDEF char *nob_temp_running_executable_path(void);
560580

561581
// TODO: we should probably document somewhere all the compiler we support
562582

@@ -879,20 +899,26 @@ NOBDEF bool nob_mkdir_if_not_exists(const char *path)
879899
#endif
880900
if (result < 0) {
881901
if (errno == EEXIST) {
902+
#ifndef NOB_NO_ECHO
882903
nob_log(NOB_INFO, "directory `%s` already exists", path);
904+
#endif // NOB_NO_ECHO
883905
return true;
884906
}
885907
nob_log(NOB_ERROR, "could not create directory `%s`: %s", path, strerror(errno));
886908
return false;
887909
}
888910

911+
#ifndef NOB_NO_ECHO
889912
nob_log(NOB_INFO, "created directory `%s`", path);
913+
#endif // NOB_NO_ECHO
890914
return true;
891915
}
892916

893917
NOBDEF bool nob_copy_file(const char *src_path, const char *dst_path)
894918
{
919+
#ifndef NOB_NO_ECHO
895920
nob_log(NOB_INFO, "copying %s -> %s", src_path, dst_path);
921+
#endif // NOB_NO_ECHO
896922
#ifdef _WIN32
897923
if (!CopyFile(src_path, dst_path, FALSE)) {
898924
nob_log(NOB_ERROR, "Could not copy file: %s", nob_win32_error_message(GetLastError()));
@@ -1114,12 +1140,14 @@ static Nob_Proc nob__cmd_start_process(Nob_Cmd cmd, Nob_Fd *fdin, Nob_Fd *fdout,
11141140
return NOB_INVALID_PROC;
11151141
}
11161142

1143+
#ifndef NOB_NO_ECHO
11171144
Nob_String_Builder sb = {0};
11181145
nob_cmd_render(cmd, &sb);
11191146
nob_sb_append_null(&sb);
11201147
nob_log(NOB_INFO, "CMD: %s", sb.items);
11211148
nob_sb_free(sb);
11221149
memset(&sb, 0, sizeof(sb));
1150+
#endif // NOB_NO_ECHO
11231151

11241152
#ifdef _WIN32
11251153
// https://docs.microsoft.com/en-us/windows/win32/procthread/creating-a-child-process-with-redirected-input-and-output
@@ -1628,7 +1656,9 @@ NOBDEF Nob_File_Type nob_get_file_type(const char *path)
16281656

16291657
NOBDEF bool nob_delete_file(const char *path)
16301658
{
1659+
#ifndef NOB_NO_ECHO
16311660
nob_log(NOB_INFO, "deleting %s", path);
1661+
#endif // NOB_NO_ECHO
16321662
#ifdef _WIN32
16331663
if (!DeleteFileA(path)) {
16341664
nob_log(NOB_ERROR, "Could not delete file %s: %s", path, nob_win32_error_message(GetLastError()));
@@ -1718,6 +1748,15 @@ NOBDEF char *nob_temp_strdup(const char *cstr)
17181748
return result;
17191749
}
17201750

1751+
NOBDEF char *nob_temp_strndup(const char *s, size_t n)
1752+
{
1753+
char *r = nob_temp_alloc(n + 1);
1754+
NOB_ASSERT(r != NULL && "Extend the size of the temporary allocator");
1755+
memcpy(r, s, n);
1756+
r[n] = '\0';
1757+
return r;
1758+
}
1759+
17211760
NOBDEF void *nob_temp_alloc(size_t requested_size)
17221761
{
17231762
size_t word_size = sizeof(uintptr_t);
@@ -1763,11 +1802,7 @@ NOBDEF void nob_temp_rewind(size_t checkpoint)
17631802

17641803
NOBDEF const char *nob_temp_sv_to_cstr(Nob_String_View sv)
17651804
{
1766-
char *result = (char*)nob_temp_alloc(sv.count + 1);
1767-
NOB_ASSERT(result != NULL && "Extend the size of the temporary allocator");
1768-
memcpy(result, sv.data, sv.count);
1769-
result[sv.count] = '\0';
1770-
return result;
1805+
return nob_temp_strndup(sv.data, sv.count);
17711806
}
17721807

17731808
NOBDEF int nob_needs_rebuild(const char *output_path, const char **input_paths, size_t input_paths_count)
@@ -1858,7 +1893,9 @@ NOBDEF const char *nob_path_name(const char *path)
18581893

18591894
NOBDEF bool nob_rename(const char *old_path, const char *new_path)
18601895
{
1896+
#ifndef NOB_NO_ECHO
18611897
nob_log(NOB_INFO, "renaming %s -> %s", old_path, new_path);
1898+
#endif // NOB_NO_ECHO
18621899
#ifdef _WIN32
18631900
if (!MoveFileEx(old_path, new_path, MOVEFILE_REPLACE_EXISTING)) {
18641901
nob_log(NOB_ERROR, "could not rename %s to %s: %s", old_path, new_path, nob_win32_error_message(GetLastError()));
@@ -1932,6 +1969,15 @@ NOBDEF int nob_sb_appendf(Nob_String_Builder *sb, const char *fmt, ...)
19321969
return n;
19331970
}
19341971

1972+
NOBDEF void nob_sb_pad_align(Nob_String_Builder *sb, size_t size)
1973+
{
1974+
size_t rem = sb->count%size;
1975+
if (rem == 0) return;
1976+
for (size_t i = 0; i < size - rem; ++i) {
1977+
nob_da_append(sb, 0);
1978+
}
1979+
}
1980+
19351981
NOBDEF Nob_String_View nob_sv_chop_by_delim(Nob_String_View *sv, char delim)
19361982
{
19371983
size_t i = 0;
@@ -2100,6 +2146,89 @@ NOBDEF bool nob_set_current_dir(const char *path)
21002146
#endif // _WIN32
21012147
}
21022148

2149+
NOBDEF char *nob_temp_dir_name(const char *path)
2150+
{
2151+
#ifndef _WIN32
2152+
// Stolen from the musl's implementation of dirname.
2153+
// We are implementing our own one because libc vendors cannot agree on whether dirname(3)
2154+
// modifies the path or not.
2155+
if (!path || !*path) return ".";
2156+
size_t i = strlen(path) - 1;
2157+
for (; path[i] == '/'; i--) if (!i) return "/";
2158+
for (; path[i] != '/'; i--) if (!i) return ".";
2159+
for (; path[i] == '/'; i--) if (!i) return "/";
2160+
return nob_temp_strndup(path, i + 1);
2161+
#else
2162+
if (!path) path = ""; // Treating NULL as empty.
2163+
char *drive = nob_temp_alloc(_MAX_DRIVE);
2164+
char *dir = nob_temp_alloc(_MAX_DIR);
2165+
// https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/8e46eyt7(v=vs.100)
2166+
errno_t ret = _splitpath_s(path, drive, _MAX_DRIVE, dir, _MAX_DIR, NULL, 0, NULL, 0);
2167+
NOB_ASSERT(ret == 0);
2168+
return nob_temp_sprintf("%s%s", drive, dir);
2169+
#endif // _WIN32
2170+
}
2171+
2172+
NOBDEF char *nob_temp_file_name(const char *path)
2173+
{
2174+
#ifndef _WIN32
2175+
// Stolen from the musl's implementation of dirname.
2176+
// We are implementing our own one because libc vendors cannot agree on whether basename(3)
2177+
// modifies the path or not.
2178+
if (!path || !*path) return ".";
2179+
char *s = nob_temp_strdup(path);
2180+
size_t i = strlen(s)-1;
2181+
for (; i&&s[i]=='/'; i--) s[i] = 0;
2182+
for (; i&&s[i-1]!='/'; i--);
2183+
return s+i;
2184+
#else
2185+
if (!path) path = ""; // Treating NULL as empty.
2186+
char *fname = nob_temp_alloc(_MAX_FNAME);
2187+
char *ext = nob_temp_alloc(_MAX_EXT);
2188+
// https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/8e46eyt7(v=vs.100)
2189+
errno_t ret = _splitpath_s(path, NULL, 0, NULL, 0, fname, _MAX_FNAME, ext, _MAX_EXT);
2190+
NOB_ASSERT(ret == 0);
2191+
return nob_temp_sprintf("%s%s", fname, ext);
2192+
#endif // _WIN32
2193+
}
2194+
2195+
NOBDEF char *nob_temp_file_ext(const char *path)
2196+
{
2197+
#ifndef _WIN32
2198+
return strrchr(nob_temp_file_name(path), '.');
2199+
#else
2200+
if (!path) path = ""; // Treating NULL as empty.
2201+
char *ext = nob_temp_alloc(_MAX_EXT);
2202+
// https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/8e46eyt7(v=vs.100)
2203+
errno_t ret = _splitpath_s(path, NULL, 0, NULL, 0, NULL, 0, ext, _MAX_EXT);
2204+
NOB_ASSERT(ret == 0);
2205+
return ext;
2206+
#endif // _WIN32
2207+
}
2208+
2209+
NOBDEF char *nob_temp_running_executable_path(void)
2210+
{
2211+
#if defined(__linux__)
2212+
char buf[4096];
2213+
int length = readlink("/proc/self/exe", buf, NOB_ARRAY_LEN(buf));
2214+
if (length < 0) return "";
2215+
return nob_temp_strndup(buf, length);
2216+
#elif defined(_WIN32)
2217+
char buf[MAX_PATH];
2218+
int length = GetModuleFileNameA(NULL, buf, MAX_PATH);
2219+
return nob_temp_strndup(buf, length);
2220+
#elif defined(__APPLE__)
2221+
char buf[4096];
2222+
uint32_t size = NOB_ARRAY_LEN(buf);
2223+
if (_NSGetExecutablePath(buf, &size) != 0) return "";
2224+
int length = strlen(buf);
2225+
return nob_temp_strndup(buf, length);
2226+
#else
2227+
fprintf(stderr, "%s:%d: TODO: nob_temp_running_executable_path is not implemented for this platform\n", __FILE__, __LINE__);
2228+
return "";
2229+
#endif
2230+
}
2231+
21032232
// minirent.h SOURCE BEGIN ////////////////////////////////////////
21042233
#if defined(_WIN32) && !defined(NOB_NO_MINIRENT)
21052234
struct DIR
@@ -2236,12 +2365,14 @@ NOBDEF int closedir(DIR *dirp)
22362365
#define da_last nob_da_last
22372366
#define da_remove_unordered nob_da_remove_unordered
22382367
#define da_foreach nob_da_foreach
2368+
#define swap nob_swap
22392369
#define String_Builder Nob_String_Builder
22402370
#define read_entire_file nob_read_entire_file
22412371
#define sb_appendf nob_sb_appendf
22422372
#define sb_append_buf nob_sb_append_buf
22432373
#define sb_append_cstr nob_sb_append_cstr
22442374
#define sb_append_null nob_sb_append_null
2375+
#define sb_pad_align nob_sb_pad_align
22452376
#define sb_free nob_sb_free
22462377
#define Proc Nob_Proc
22472378
#define INVALID_PROC NOB_INVALID_PROC
@@ -2274,6 +2405,7 @@ NOBDEF int closedir(DIR *dirp)
22742405
#define cmd_run_sync_redirect nob_cmd_run_sync_redirect
22752406
#define cmd_run_sync_redirect_and_reset nob_cmd_run_sync_redirect_and_reset
22762407
#define temp_strdup nob_temp_strdup
2408+
#define temp_strndup nob_temp_strndup
22772409
#define temp_alloc nob_temp_alloc
22782410
#define temp_sprintf nob_temp_sprintf
22792411
#define temp_reset nob_temp_reset
@@ -2287,6 +2419,10 @@ NOBDEF int closedir(DIR *dirp)
22872419
#define file_exists nob_file_exists
22882420
#define get_current_dir_temp nob_get_current_dir_temp
22892421
#define set_current_dir nob_set_current_dir
2422+
#define temp_dir_name nob_temp_dir_name
2423+
#define temp_file_name nob_temp_file_name
2424+
#define temp_file_ext nob_temp_file_ext
2425+
#define temp_running_executable_path nob_temp_running_executable_path
22902426
#define String_View Nob_String_View
22912427
#define temp_sv_to_cstr nob_temp_sv_to_cstr
22922428
#define sv_chop_by_delim nob_sv_chop_by_delim
@@ -2310,6 +2446,14 @@ NOBDEF int closedir(DIR *dirp)
23102446
/*
23112447
Revision history:
23122448
2449+
1.25.0 (2025-10-25) - Add nob_sb_pad_align()
2450+
- Add nob_swap()
2451+
- Add nob_temp_strndup()
2452+
- Add nob_temp_dir_name()
2453+
- Add nob_temp_file_name()
2454+
- Add nob_temp_file_ext()
2455+
- Add nob_temp_running_executable_path()
2456+
1.24.0 (2025-10-23) Introduce NOB_NO_ECHO macro flag (@rexim)
23132457
1.23.0 (2025-08-22) Introduce new API for running commands (by @rexim, @programmerlexi, @0x152a)
23142458
- Add nob_cmd_run()
23152459
- Add nob_cmd_run_opt()

0 commit comments

Comments
 (0)