@@ -403,40 +403,41 @@ const char* StrReadFmtInternal(const char* input, const char* fmtstr, TypeSpecif
403403
404404 const char * p = fmtstr ;
405405 const char * in = input ;
406- size remaining = ZstrLen (fmtstr );
407- size arg_index = 0 ; // Current argument index
406+ u64 rem_p = ZstrLen (fmtstr );
407+ u64 rem_in = ZstrLen (in );
408+ u64 arg_index = 0 ; // Current argument index
408409
409- while (remaining > 0 ) {
410- if (remaining >= 2 && p [0 ] == '{' && p [1 ] == '{' ) {
410+ while (rem_p > 0 ) {
411+ if (rem_p >= 2 && p [0 ] == '{' && p [1 ] == '{' ) {
411412 if (!in || * in != '{' ) {
412413 LOG_ERROR ("Expected '{' in input" );
413414 return NULL ;
414415 }
415416 in ++ ;
416- p += 2 ;
417- remaining -= 2 ;
418- } else if (remaining >= 2 && p [0 ] == '}' && p [1 ] == '}' ) {
417+ p += 2 ;
418+ rem_p -= 2 ;
419+ } else if (rem_p >= 2 && p [0 ] == '}' && p [1 ] == '}' ) {
419420 if (!in || * in != '}' ) {
420421 LOG_ERROR ("Expected '}' in input" );
421422 return NULL ;
422423 }
423424 in ++ ;
424- p += 2 ;
425- remaining -= 2 ;
425+ p += 2 ;
426+ rem_p -= 2 ;
426427 } else if (p [0 ] == '{' ) {
427428 p ++ ;
428- remaining -- ;
429+ rem_p -- ;
429430
430431 // Find closing brace
431432 const char * start = p ;
432433 size spec_len = 0 ;
433- while (remaining > 0 && * p != '}' ) {
434+ while (rem_p > 0 && * p != '}' ) {
434435 p ++ ;
435- remaining -- ;
436+ rem_p -- ;
436437 spec_len ++ ;
437438 }
438439
439- if (remaining == 0 || * p != '}' ) {
440+ if (rem_p == 0 || * p != '}' ) {
440441 LOG_ERROR ("Unmatched '{' in format string" );
441442 return NULL ;
442443 }
@@ -457,11 +458,16 @@ const char* StrReadFmtInternal(const char* input, const char* fmtstr, TypeSpecif
457458 spec_buf [spec_len ] = '\0' ;
458459
459460 // Validate format specifier
460- FmtInfo fmt_info ;
461+ FmtInfo fmt_info = { 0 } ;
461462 if (!ParseFormatSpec (spec_buf , spec_len , & fmt_info )) {
462463 LOG_ERROR ("Failed to parse format specifier" );
463464 return NULL ; // Error already logged by ParseFormatSpec
464465 }
466+ fmt_info .max_read_len = rem_in ;
467+
468+ // Skip closing '}'
469+ p ++ ;
470+ rem_p -- ;
465471
466472 // Use the type-specific reader
467473 TypeSpecificIO * io = & argv [arg_index ++ ];
@@ -501,6 +507,10 @@ const char* StrReadFmtInternal(const char* input, const char* fmtstr, TypeSpecif
501507 u64 x = 0 ;
502508 next = raw_reader (in , & fmt_info , & x );
503509
510+ if (next ) {
511+ rem_in -= (next - in );
512+ }
513+
504514 // deduce the actual field size
505515 u32 var_width = 0 ;
506516 void * read_fn = (void * )io -> reader ;
@@ -548,8 +558,37 @@ const char* StrReadFmtInternal(const char* input, const char* fmtstr, TypeSpecif
548558 }
549559 }
550560 } else {
561+ // find length between two format specifiers
562+ u64 space_len = 0 ;
563+ char c = p [space_len ];
564+ while (c ) {
565+ // if this is possible start of a new format specifier and not '{{' (escaped brace)
566+ if (c == '{' && p [space_len + 1 ] != '{' ) {
567+ break ;
568+ } else {
569+ space_len ++ ;
570+ }
571+ c = p [space_len ];
572+ }
573+
574+ // if there's something between two format specifiers then we can read only upto that
575+ // otherwise end of input is the limit
576+ if (space_len ) {
577+ // Find first occurence of content between current and next format specifier or null character
578+ const char * e = NULL ;
579+ if ((e = ZstrFindSubstringN (in , p , space_len ))) {
580+ fmt_info .max_read_len = e - in ;
581+ }
582+ } else {
583+ fmt_info .max_read_len = rem_in ;
584+ }
585+
551586 // do formatted read
552587 next = io -> reader (in , & fmt_info , io -> data );
588+
589+ if (next ) {
590+ rem_in -= (next - in );
591+ }
553592 }
554593
555594 // Check if reading failed
@@ -560,10 +599,6 @@ const char* StrReadFmtInternal(const char* input, const char* fmtstr, TypeSpecif
560599
561600 // Update input pointer
562601 in = next ;
563-
564- // Skip closing '}'
565- p ++ ;
566- remaining -- ;
567602 } else {
568603 // Match exact character from format string
569604 if (!in || * in != * p ) {
@@ -576,7 +611,8 @@ const char* StrReadFmtInternal(const char* input, const char* fmtstr, TypeSpecif
576611 }
577612 in ++ ;
578613 p ++ ;
579- remaining -- ;
614+ rem_p -- ;
615+ rem_in -- ;
580616 }
581617 }
582618
@@ -1259,10 +1295,7 @@ const char* _read_Str(const char* i, FmtInfo* fmt_info, Str* s) {
12591295 bool force_case = fmt_info && (fmt_info -> flags & FMT_FLAG_FORCE_CASE ) != 0 ;
12601296 bool is_caps = fmt_info && (fmt_info -> flags & FMT_FLAG_CAPS ) != 0 ;
12611297 bool is_string = fmt_info && (fmt_info -> flags & FMT_FLAG_STRING ) != 0 ;
1262-
1263- // Skip leading whitespace
1264- while (IS_SPACE (* i ))
1265- i ++ ;
1298+ u32 r = fmt_info -> max_read_len ;
12661299
12671300 // Check for empty input
12681301 if (!* i ) {
@@ -1274,9 +1307,10 @@ const char* _read_Str(const char* i, FmtInfo* fmt_info, Str* s) {
12741307 char quote = 0 ;
12751308 if (is_string && (* i == '"' || * i == '\'' )) {
12761309 quote = * i ++ ;
1310+ r -- ;
12771311 }
12781312
1279- while (* i ) {
1313+ while (r && * i ) {
12801314 if (quote ) {
12811315 // Quoted string mode
12821316 if (* i == '\\' ) {
@@ -1286,7 +1320,8 @@ const char* _read_Str(const char* i, FmtInfo* fmt_info, Str* s) {
12861320 StrDeinit (s );
12871321 return NULL ;
12881322 }
1289- i = curr + 1 ; // Move past the escape sequence
1323+ i = curr + 1 ; // Move past the escape sequence
1324+ r -= 2 ;
12901325
12911326 // Apply case conversion if needed
12921327 if (force_case ) {
@@ -1296,9 +1331,11 @@ const char* _read_Str(const char* i, FmtInfo* fmt_info, Str* s) {
12961331 StrPushBack (s , c );
12971332 } else if (* i == quote ) {
12981333 i ++ ; // Skip closing quote
1334+ r -- ;
12991335 return i ; // Successfully read quoted string
13001336 } else {
13011337 char c = * i ++ ;
1338+ r -- ;
13021339
13031340 // Apply case conversion if needed
13041341 if (force_case ) {
@@ -1309,7 +1346,7 @@ const char* _read_Str(const char* i, FmtInfo* fmt_info, Str* s) {
13091346 }
13101347 } else {
13111348 // Unquoted string mode - read until whitespace
1312- if (IS_SPACE (* i )) {
1349+ if (is_string && IS_SPACE (* i )) {
13131350 return i ; // Successfully read unquoted string
13141351 }
13151352
@@ -1320,7 +1357,8 @@ const char* _read_Str(const char* i, FmtInfo* fmt_info, Str* s) {
13201357 StrDeinit (s );
13211358 return NULL ;
13221359 }
1323- i = curr + 1 ; // Move past the escape sequence
1360+ i = curr + 1 ; // Move past the escape sequence
1361+ r -= 2 ;
13241362
13251363 // Apply case conversion if needed
13261364 if (force_case ) {
@@ -1330,6 +1368,7 @@ const char* _read_Str(const char* i, FmtInfo* fmt_info, Str* s) {
13301368 StrPushBack (s , c );
13311369 } else {
13321370 char c = * i ++ ;
1371+ r -- ;
13331372
13341373 // Apply case conversion if needed
13351374 if (force_case ) {
0 commit comments