@@ -1602,19 +1602,18 @@ NOBDEF void nob_log(Nob_Log_Level level, const char *fmt, ...)
16021602 va_end (args );
16031603}
16041604
1605- bool nob__walk_dir_opt_impl (const char * root , Nob_Walk_Func func , size_t level , bool * stop , Nob_Walk_Dir_Opt opt )
1605+ bool nob__walk_dir_opt_impl (Nob_String_Builder * sb , Nob_Walk_Func func , size_t level , bool * stop , Nob_Walk_Dir_Opt opt )
16061606{
16071607#ifdef _WIN32
16081608 bool result = true;
1609- Nob_String_Builder sb = {0 };
16101609 WIN32_FIND_DATA data ;
16111610 HANDLE hFind = INVALID_HANDLE_VALUE ;
16121611
1613- Nob_File_Type type = nob_get_file_type (root );
1612+ Nob_File_Type type = nob_get_file_type (sb -> items );
16141613 if (type < 0 ) nob_return_defer (false);
16151614 Nob_Walk_Action action = NOB_WALK_CONT ;
16161615 if (!func ((Nob_Walk_Entry ) {
1617- .path = root ,
1616+ .path = sb -> items ,
16181617 .type = type ,
16191618 .data = opt .data ,
16201619 .level = level ,
@@ -1632,48 +1631,46 @@ bool nob__walk_dir_opt_impl(const char *root, Nob_Walk_Func func, size_t level,
16321631
16331632 {
16341633 size_t mark = nob_temp_save ();
1635- char * buffer = nob_temp_sprintf ("%s\\*" , root );
1634+ char * buffer = nob_temp_sprintf ("%s\\*" , sb -> items );
16361635 hFind = FindFirstFile (buffer , & data );
16371636 nob_temp_rewind (mark );
16381637 }
16391638
16401639 if (hFind == INVALID_HANDLE_VALUE ) {
1641- nob_log (NOB_ERROR , "Could not open directory %s: %s" , root , nob_win32_error_message (GetLastError ()));
1640+ nob_log (NOB_ERROR , "Could not open directory %s: %s" , sb -> items , nob_win32_error_message (GetLastError ()));
16421641 nob_return_defer (false);
16431642 }
16441643
1644+ size_t mark = sb -> count - 1 ;
16451645 for (;;) {
16461646 if (strcmp (data .cFileName , "." ) != 0 && strcmp (data .cFileName , ".." ) != 0 ) {
1647- sb .count = 0 ;
1648- nob_sb_appendf (& sb , "%s/%s" , root , data .cFileName );
1649- nob_sb_append_null (& sb );
1650- const char * path = sb .items ;
1651- if (!nob__walk_dir_opt_impl (path , func , level + 1 , stop , opt )) nob_return_defer (false);
1647+ sb -> count = mark ;
1648+ nob_sb_appendf (sb , "\\%s" , data .cFileName );
1649+ nob_sb_append_null (sb );
1650+ if (!nob__walk_dir_opt_impl (sb , func , level + 1 , stop , opt )) nob_return_defer (false);
16521651 if (* stop ) nob_return_defer (true);
16531652 }
16541653
16551654 if (!FindNextFile (hFind , & data )) {
16561655 if (GetLastError () == ERROR_NO_MORE_FILES ) nob_return_defer (true);
1657- nob_log (NOB_ERROR , "Could not read directory %s: %s" , root , nob_win32_error_message (GetLastError ()));
1656+ nob_log (NOB_ERROR , "Could not read directory %s: %s" , sb -> items , nob_win32_error_message (GetLastError ()));
16581657 nob_return_defer (false);
16591658 }
16601659 }
16611660
16621661defer :
16631662 FindClose (hFind );
1664- free (sb .items );
16651663 return result ;
16661664#else // POSIX
16671665 bool result = true;
16681666
16691667 DIR * dir = NULL ;
1670- Nob_String_Builder sb = {0 };
16711668
1672- Nob_File_Type type = nob_get_file_type (root );
1669+ Nob_File_Type type = nob_get_file_type (sb -> items );
16731670 if (type < 0 ) nob_return_defer (false);
16741671 Nob_Walk_Action action = NOB_WALK_CONT ;
16751672 if (!func ((Nob_Walk_Entry ) {
1676- .path = root ,
1673+ .path = sb -> items ,
16771674 .type = type ,
16781675 .data = opt .data ,
16791676 .level = level ,
@@ -1691,42 +1688,46 @@ bool nob__walk_dir_opt_impl(const char *root, Nob_Walk_Func func, size_t level,
16911688
16921689 struct dirent * ent = NULL ;
16931690
1694- dir = opendir (root );
1691+ dir = opendir (sb -> items );
16951692 if (dir == NULL ) {
1696- nob_log (NOB_ERROR , "Could not open directory %s: %s" , root , strerror (errno ));
1693+ nob_log (NOB_ERROR , "Could not open directory %s: %s" , sb -> items , strerror (errno ));
16971694 nob_return_defer (false);
16981695 }
16991696
1697+ size_t mark = sb -> count - 1 ;
17001698 errno = 0 ;
17011699 ent = readdir (dir );
17021700 while (ent != NULL ) {
17031701 if (strcmp (ent -> d_name , "." ) != 0 && strcmp (ent -> d_name , ".." ) != 0 ) {
1704- sb .count = 0 ;
1705- nob_sb_appendf (& sb , "%s/%s" , root , ent -> d_name );
1706- nob_sb_append_null (& sb );
1707- const char * path = sb .items ;
1708- if (!nob__walk_dir_opt_impl (path , func , level + 1 , stop , opt )) nob_return_defer (false);
1702+ sb -> count = mark ;
1703+ nob_sb_appendf (sb , "/%s" , ent -> d_name );
1704+ nob_sb_append_null (sb );
1705+ if (!nob__walk_dir_opt_impl (sb , func , level + 1 , stop , opt )) nob_return_defer (false);
17091706 if (* stop ) nob_return_defer (true);
17101707 }
17111708 ent = readdir (dir );
17121709 }
17131710
17141711 if (errno != 0 ) {
1715- nob_log (NOB_ERROR , "Could not read directory %s: %s" , root , strerror (errno ));
1712+ nob_log (NOB_ERROR , "Could not read directory %s: %s" , sb -> items , strerror (errno ));
17161713 nob_return_defer (false);
17171714 }
17181715
17191716defer :
17201717 if (dir ) closedir (dir );
1721- free (sb .items );
17221718 return result ;
17231719#endif // _WIN32
17241720}
17251721
17261722NOBDEF bool nob_walk_dir_opt (const char * root , Nob_Walk_Func func , Nob_Walk_Dir_Opt opt )
17271723{
17281724 bool stop = false;
1729- return nob__walk_dir_opt_impl (root , func , 0 , & stop , opt );
1725+ Nob_String_Builder sb = {0 };
1726+ nob_sb_appendf (& sb , "%s" , root );
1727+ nob_sb_append_null (& sb );
1728+ bool ok = nob__walk_dir_opt_impl (& sb , func , 0 , & stop , opt );
1729+ free (sb .items );
1730+ return ok ;
17301731}
17311732
17321733bool nob__read_entire_dir_visit (Nob_Walk_Entry entry )
@@ -2541,6 +2542,7 @@ NOBDEF char *nob_temp_running_executable_path(void)
25412542 Revision history:
25422543
25432544 2.0.1 ( ) Fix Walk_Entry naming (by @Sinha-Ujjawal)
2545+ Using single String Builder in nob__walk_dir_opt_impl (by @Sinha-Ujjawal)
25442546 2.0.0 (2026-01-06) Remove minirent.h (by @rexim)
25452547 BACKWARD INCOMPATIBLE CHANGE!!! If you were using minirent.h from this library
25462548 just use it directly from https://github.com/tsoding/minirent
0 commit comments