@@ -519,60 +519,61 @@ static void XSearch_DisplayEntry(xsearch_t *pSearch, xsearch_entry_t *pEntry)
519519int XSearch_StripEmptySpaces (xsearch_args_t * pArgs , xsearch_entry_t * pEntry )
520520{
521521 if (pEntry -> eType != XF_REGULAR ) return XSTDNON ;
522- if (! xstrused (pEntry -> sName )) return XSTDERR ;
523- if (! xstrused (pEntry -> sPath )) return XSTDERR ;
522+ XASSERT ( xstrused (pEntry -> sName ), XSTDERR ) ;
523+ XASSERT ( xstrused (pEntry -> sPath ), XSTDERR ) ;
524524
525525 char sEntry [XPATH_MAX ];
526526 xstrncpyf (sEntry , sizeof (sEntry ), "%s%s" , pEntry -> sPath , pEntry -> sName );
527527
528- xfile_t file ;
529- xbool_t bDirty = XFALSE ;
530-
531- char sLine [XLINE_MAX ];
532- size_t nLinesProcessed = 0 ;
533-
534528 xbyte_buffer_t buffer ;
535529 XByteBuffer_Init (& buffer , XLINE_MAX , XSTDNON );
536530 XASSERT ((buffer .nSize > 0 ), XSTDERR );
537531
532+ xfile_t file ;
538533 XASSERT_CALL ((XFile_Open (& file , sEntry , "r" , NULL ) > 0 ),
539534 XByteBuffer_Clear , & buffer , XSTDERR );
540535
536+ xbool_t bDirty = XFALSE ;
537+ char sLine [XLINE_MAX ];
538+
541539 int nLength = XFile_GetLine (& file , sLine , sizeof (sLine ));
542540 while (nLength > 0 )
543541 {
544- xbool_t bDropLine = XFALSE ;
545- xbool_t bModified = XFALSE ;
546- int nFirstSpace = -1 ;
542+ int nSpaceStart = -1 ;
547543 int nPosit = 0 ;
548544
549545 while (nPosit < nLength )
550546 {
551547 char cChar = sLine [nPosit ];
552548 if (cChar == '\n' ) break ;
553- if (!isspace ((unsigned char )cChar )) nFirstSpace = -1 ;
554- else if (nFirstSpace < 0 ) nFirstSpace = nPosit ;
549+ if (!isspace ((unsigned char )cChar )) nSpaceStart = -1 ;
550+ else if (nSpaceStart < 0 ) nSpaceStart = nPosit ;
555551 nPosit ++ ;
556552 }
557553
554+ xbool_t bDropLine = XFALSE ;
558555 char sNextLine [XLINE_MAX ];
559- int nNextLength = 0 ;
556+ int nNextLength = -1 ;
560557
561- if (nFirstSpace >= 0 && nFirstSpace < nLength )
558+ if (nSpaceStart >= 0 && nSpaceStart < nLength )
562559 {
563560 nNextLength = XFile_GetLine (& file , sNextLine , sizeof (sNextLine ));
564- bDropLine = ! nFirstSpace && nNextLength <= 0 && nLinesProcessed &&
565- sLine [ nLength - 1 ] != '\n' ? XTRUE : XFALSE ;
561+ xbool_t bNewLineEnding = sLine [ nLength - 1 ] == '\n' ? XTRUE : XFALSE ;
562+ xbool_t bIsLastLine = nNextLength <= 0 ? XTRUE : XFALSE ;
566563
567- if (nFirstSpace == 0 ||
568- nNextLength <= 0 ||
569- sLine [nLength - 1 ] == '\n' )
570- sLine [nFirstSpace ++ ] = '\n' ;
564+ // Drop last line if it's only whitespace and does not have a newline ending
565+ // buffer.nUsed guarantees that we have anyway a newline in the previous line
566+ bDropLine = !nSpaceStart && !bNewLineEnding && bIsLastLine && buffer .nUsed ? XTRUE : XFALSE ;
571567
572- nLength = nFirstSpace ;
573- sLine [nLength ] = '\0' ;
568+ if (!bDropLine )
569+ {
570+ if (!nSpaceStart || bNewLineEnding )
571+ sLine [nSpaceStart ++ ] = '\n' ;
572+
573+ nLength = nSpaceStart ;
574+ sLine [nLength ] = '\0' ;
575+ }
574576
575- bModified = XTRUE ;
576577 bDirty = XTRUE ;
577578 }
578579
@@ -582,26 +583,24 @@ int XSearch_StripEmptySpaces(xsearch_args_t *pArgs, xsearch_entry_t *pEntry)
582583 XByteBuffer_Clear , & buffer , XFile_Close , & file , XSTDERR );
583584 }
584585
585- if (bModified )
586+ if (nNextLength >= 0 )
586587 {
587- if (nNextLength > 0 )
588- xstrncpy (sLine , sizeof (sLine ), sNextLine );
589-
588+ xstrncpys (sLine , sizeof (sLine ), sNextLine , (size_t )nNextLength );
590589 nLength = nNextLength ;
591- nLinesProcessed ++ ;
592590 continue ;
593591 }
594592
595593 nLength = XFile_GetLine (& file , sLine , sizeof (sLine ));
596- nLinesProcessed ++ ;
597594 }
598595
599596 // Finished reading
600597 XFile_Close (& file );
601598
602- if (pArgs -> bFinalNewline && (!buffer .nUsed || buffer .pData [buffer .nUsed - 1 ] != '\n' ))
599+ if (pArgs -> bFinalNewline && buffer .nUsed &&
600+ buffer .pData [buffer .nUsed - 1 ] != '\n' )
603601 {
604- XASSERT_CALL ((XByteBuffer_Add (& buffer , (const uint8_t * )"\n" , 1 ) > 0 ),
602+ XASSERT_CALL ((XByteBuffer_Add (& buffer ,
603+ (const uint8_t * )"\n" , sizeof ("\n" ) - 1 ) > 0 ),
605604 XByteBuffer_Clear , & buffer , XSTDERR );
606605
607606 bDirty = XTRUE ;
@@ -619,31 +618,33 @@ int XSearch_StripEmptySpaces(xsearch_args_t *pArgs, xsearch_entry_t *pEntry)
619618 XASSERT_CALL ((rename (sEntry , sEntryBackup ) == 0 ),
620619 XByteBuffer_Clear , & buffer , XSTDERR );
621620
622- if (XPath_Exists ( sEntryBackup ) )
621+ if (XFile_OpenM ( & file , sEntry , "cwt" , pEntry -> nMode ) < 0 )
623622 {
624- if (XFile_OpenM (& file , sEntry , "cwt" , pEntry -> nMode ) < 0 )
625- {
626- xloge ("Failed to open file: %s (%s)" , sEntry , XSTRERR );
627- rename (sEntryBackup , sEntry );
623+ xloge ("Failed to open file: %s (%s)" , sEntry , XSTRERR );
628624
629- XByteBuffer_Clear (& buffer );
630- return XSTDERR ;
631- }
625+ if (rename (sEntryBackup , sEntry ) != 0 )
626+ xloge ("Failed to restore backup: %s -> %s (%s)" , sEntryBackup , sEntry , XSTRERR );
632627
633- if (XFile_Write (& file , buffer .pData , buffer .nUsed ) <= 0 )
634- {
635- xloge ("Failed to write file: %s (%s)" , sEntry , XSTRERR );
636- rename (sEntryBackup , sEntry );
628+ XByteBuffer_Clear (& buffer );
629+ return XSTDERR ;
630+ }
637631
638- XByteBuffer_Clear ( & buffer );
639- return XSTDERR ;
640- }
632+ if ( XFile_Write ( & file , buffer . pData , buffer . nUsed ) <= 0 )
633+ {
634+ xloge ( "Failed to write file: %s (%s)" , sEntry , XSTRERR );
641635
636+ if (rename (sEntryBackup , sEntry ) != 0 )
637+ xloge ("Failed to restore backup: %s -> %s (%s)" , sEntryBackup , sEntry , XSTRERR );
638+
639+ XByteBuffer_Clear (& buffer );
642640 XFile_Close (& file );
643- unlink ( sEntryBackup ) ;
641+ return XSTDERR ;
644642 }
645643
646644 XByteBuffer_Clear (& buffer );
645+ XFile_Close (& file );
646+
647+ unlink (sEntryBackup );
647648 return XSTDOK ;
648649}
649650
0 commit comments