1- /* nob - v3.5 .0 - Public Domain - https://github.com/tsoding/nob.h
1+ /* nob - v3.6 .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
@@ -216,7 +216,7 @@ typedef enum {
216216 NOB_NO_LOGS ,
217217} Nob_Log_Level ;
218218
219- // Any messages with the level below nob_minimal_log_level are going to be suppressed.
219+ // Any messages with the level below nob_minimal_log_level are going to be suppressed by the nob_default_log_handler .
220220extern Nob_Log_Level nob_minimal_log_level ;
221221
222222typedef void (Nob_Log_Handler )(Nob_Log_Level level , const char * fmt , va_list args );
@@ -888,15 +888,28 @@ NOBDEF const char *nob_temp_sv_to_cstr(Nob_String_View sv);
888888NOBDEF Nob_String_View nob_sv_chop_while (Nob_String_View * sv , int (* p )(int x ));
889889NOBDEF Nob_String_View nob_sv_chop_by_delim (Nob_String_View * sv , char delim );
890890NOBDEF Nob_String_View nob_sv_chop_left (Nob_String_View * sv , size_t n );
891+ NOBDEF Nob_String_View nob_sv_chop_right (Nob_String_View * sv , size_t n );
891892// If `sv` starts with `prefix` chops off the prefix and returns true.
892893// Otherwise, leaves `sv` unmodified and returns false.
893894NOBDEF bool nob_sv_chop_prefix (Nob_String_View * sv , Nob_String_View prefix );
895+ // If `sv` ends with `suffix` chops off the suffix and returns true.
896+ // Otherwise, leaves `sv` unmodified and returns false.
897+ NOBDEF bool nob_sv_chop_suffix (Nob_String_View * sv , Nob_String_View suffix );
894898NOBDEF Nob_String_View nob_sv_trim (Nob_String_View sv );
895899NOBDEF Nob_String_View nob_sv_trim_left (Nob_String_View sv );
896900NOBDEF Nob_String_View nob_sv_trim_right (Nob_String_View sv );
897901NOBDEF bool nob_sv_eq (Nob_String_View a , Nob_String_View b );
902+ NOB_DEPRECATED ("Use nob_sv_ends_with_cstr(sv, suffix) instead. "
903+ "Pay attention to the `s` at the end of the `end`. "
904+ "The reason this function was deprecated is because "
905+ "of the typo in the name, of course, but also "
906+ "because the second argument was a NULL-terminated string "
907+ "while nob_sv_starts_with() accepted Nob_String_View as the "
908+ "prefix which created an inconsistency in the API." )
898909NOBDEF bool nob_sv_end_with (Nob_String_View sv , const char * cstr );
899- NOBDEF bool nob_sv_starts_with (Nob_String_View sv , Nob_String_View expected_prefix );
910+ NOBDEF bool nob_sv_ends_with_cstr (Nob_String_View sv , const char * cstr );
911+ NOBDEF bool nob_sv_ends_with (Nob_String_View sv , Nob_String_View suffix );
912+ NOBDEF bool nob_sv_starts_with (Nob_String_View sv , Nob_String_View prefix );
900913NOBDEF Nob_String_View nob_sv_from_cstr (const char * cstr );
901914NOBDEF Nob_String_View nob_sv_from_parts (const char * data , size_t count );
902915// nob_sb_to_sv() enables you to just view Nob_String_Builder as Nob_String_View
@@ -992,7 +1005,7 @@ NOBDEF void nob__go_rebuild_urself(int argc, char **argv, const char *source_pat
9921005#ifdef _WIN32
9931006 // On Windows executables almost always invoked without extension, so
9941007 // it's ./nob, not ./nob.exe. For renaming the extension is a must.
995- if (!nob_sv_end_with (nob_sv_from_cstr (binary_path ), ".exe" )) {
1008+ if (!nob_sv_ends_with_cstr (nob_sv_from_cstr (binary_path ), ".exe" )) {
9961009 binary_path = nob_temp_sprintf ("%s.exe" , binary_path );
9971010 }
9981011#endif
@@ -2553,6 +2566,15 @@ NOBDEF bool nob_sv_chop_prefix(Nob_String_View *sv, Nob_String_View prefix)
25532566 return false;
25542567}
25552568
2569+ NOBDEF bool nob_sv_chop_suffix (Nob_String_View * sv , Nob_String_View suffix )
2570+ {
2571+ if (nob_sv_ends_with (* sv , suffix )) {
2572+ nob_sv_chop_right (sv , suffix .count );
2573+ return true;
2574+ }
2575+ return false;
2576+ }
2577+
25562578NOBDEF Nob_String_View nob_sv_chop_left (Nob_String_View * sv , size_t n )
25572579{
25582580 if (n > sv -> count ) {
@@ -2567,6 +2589,19 @@ NOBDEF Nob_String_View nob_sv_chop_left(Nob_String_View *sv, size_t n)
25672589 return result ;
25682590}
25692591
2592+ NOBDEF Nob_String_View nob_sv_chop_right (Nob_String_View * sv , size_t n )
2593+ {
2594+ if (n > sv -> count ) {
2595+ n = sv -> count ;
2596+ }
2597+
2598+ Nob_String_View result = nob_sv_from_parts (sv -> data + sv -> count - n , n );
2599+
2600+ sv -> count -= n ;
2601+
2602+ return result ;
2603+ }
2604+
25702605NOBDEF Nob_String_View nob_sv_from_parts (const char * data , size_t count )
25712606{
25722607 Nob_String_View sv ;
@@ -2616,16 +2651,26 @@ NOBDEF bool nob_sv_eq(Nob_String_View a, Nob_String_View b)
26162651
26172652NOBDEF bool nob_sv_end_with (Nob_String_View sv , const char * cstr )
26182653{
2619- size_t cstr_count = strlen (cstr );
2620- if (sv .count >= cstr_count ) {
2621- size_t ending_start = sv .count - cstr_count ;
2622- Nob_String_View sv_ending = nob_sv_from_parts (sv .data + ending_start , cstr_count );
2623- return nob_sv_eq (sv_ending , nob_sv_from_cstr (cstr ));
2654+ return nob_sv_ends_with_cstr (sv , cstr );
2655+ }
2656+
2657+ NOBDEF bool nob_sv_ends_with_cstr (Nob_String_View sv , const char * cstr )
2658+ {
2659+ return nob_sv_ends_with (sv , nob_sv_from_cstr (cstr ));
2660+ }
2661+
2662+ NOBDEF bool nob_sv_ends_with (Nob_String_View sv , Nob_String_View suffix )
2663+ {
2664+ if (sv .count >= suffix .count ) {
2665+ Nob_String_View sv_tail = {
2666+ .count = suffix .count ,
2667+ .data = sv .data + sv .count - suffix .count ,
2668+ };
2669+ return nob_sv_eq (sv_tail , suffix );
26242670 }
26252671 return false;
26262672}
26272673
2628-
26292674NOBDEF bool nob_sv_starts_with (Nob_String_View sv , Nob_String_View expected_prefix )
26302675{
26312676 if (expected_prefix .count <= sv .count ) {
@@ -2939,13 +2984,17 @@ NOBDEF char *nob_temp_running_executable_path(void)
29392984 #define sv_chop_by_delim nob_sv_chop_by_delim
29402985 #define sv_chop_while nob_sv_chop_while
29412986 #define sv_chop_prefix nob_sv_chop_prefix
2987+ #define sv_chop_suffix nob_sv_chop_suffix
29422988 #define sv_chop_left nob_sv_chop_left
2989+ #define sv_chop_right nob_sv_chop_right
29432990 #define sv_trim nob_sv_trim
29442991 #define sv_trim_left nob_sv_trim_left
29452992 #define sv_trim_right nob_sv_trim_right
29462993 #define sv_eq nob_sv_eq
29472994 #define sv_starts_with nob_sv_starts_with
29482995 #define sv_end_with nob_sv_end_with
2996+ #define sv_ends_with nob_sv_ends_with
2997+ #define sv_ends_with_cstr nob_sv_ends_with_cstr
29492998 #define sv_from_cstr nob_sv_from_cstr
29502999 #define sv_from_parts nob_sv_from_parts
29513000 #define sb_to_sv nob_sb_to_sv
@@ -2959,7 +3008,12 @@ NOBDEF char *nob_temp_running_executable_path(void)
29593008/*
29603009 Revision history:
29613010
2962- 3.5.0 (2026-03-13) Add nob_null_log_handler (by @rexim)
3011+ 3.6.0 (2026-03-16) Add nob_sv_chop_suffix()
3012+ Deprecate nob_sv_end_with()
3013+ Add nob_sv_ends_with_cstr() instead of nob_sv_end_with()
3014+ Add nob_sv_ends_with()
3015+ Add nob_sv_chop_right()
3016+ 3.5.0 (2026-03-13) Add nob_null_log_handler() (by @rexim)
29633017 Rename nob_log_handler to Nob_Log_Handler (by @rexim)
29643018 3.4.0 (2026-03-12) Add nob_da_first() (by @rexim)
29653019 Add nob_da_pop() (by @rexim)
0 commit comments