@@ -14,15 +14,24 @@ pub fn main() !void {
1414 const patch_file_path = args [2 ];
1515 const output_path = args [3 ];
1616
17- const patch_file = try std .fs .openFileAbsolute (patch_file_path , .{ .mode = .read_only });
18- defer patch_file .close ();
19- const chunk_details = Chunk .next (allocator , patch_file ) orelse @panic ("No chunk data found" );
17+ const patch_file = patch_file : {
18+ const patch_file = try std .fs .cwd ().openFile (patch_file_path , .{ .mode = .read_only });
19+ defer patch_file .close ();
20+ var patch_buf : [4096 ]u8 = undefined ;
21+ var reader = patch_file .reader (& patch_buf );
22+ break :patch_file try reader .interface .allocRemaining (allocator , .unlimited );
23+ };
24+ const chunk_details = Chunk .init (allocator , patch_file , 0 ) orelse @panic ("No chunk data found" );
2025
21- const file = try std .fs .openFileAbsolute (file_path , .{ .mode = .read_only });
26+ const file = try std .fs .cwd (). openFile (file_path , .{ .mode = .read_only });
2227 defer file .close ();
28+ var in_buf : [4096 ]u8 = undefined ;
29+ var reader = file .reader (& in_buf );
2330
24- const output = try std .fs .createFileAbsolute (output_path , .{});
31+ const output = try std .fs .cwd (). createFile (output_path , .{});
2532 defer output .close ();
33+ var out_buf : [4096 ]u8 = undefined ;
34+ var writer = output .writer (& out_buf );
2635
2736 var state : State = .copy ;
2837
@@ -32,26 +41,41 @@ pub fn main() !void {
3241
3342 switch (state ) {
3443 .copy = > {
35- const line = getLine (allocator , file ) orelse return ;
36- _ = try output .write (line );
37- _ = try output .write ("\n " );
44+ _ = try reader .interface .streamDelimiterEnding (& writer .interface , '\n ' );
45+ _ = reader .interface .takeByte () catch | err | switch (err ) {
46+ error .EndOfStream = > {
47+ try writer .end ();
48+ return ;
49+ },
50+ else = > return err ,
51+ };
52+ try writer .interface .writeByte ('\n ' );
3853 },
3954 .chunk = > {
4055 const chunk = chunk_details .lines [line_number - chunk_details .src ];
4156 switch (chunk .action ) {
4257 .remove = > {
43- const line = getLine (allocator , file ) orelse return ;
58+ const line = reader .interface .takeDelimiterExclusive ('\n ' ) catch | err | switch (err ) {
59+ error .EndOfStream = > return ,
60+ else = > return err ,
61+ };
4462 if (! std .mem .eql (u8 , chunk .buf , line )) @panic ("Failed to apply patch" );
4563 },
4664 .keep = > {
47- const line = getLine (allocator , file ) orelse return ;
48- if (! std .mem .eql (u8 , chunk .buf , line )) @panic ("Failed to apply patch" );
49- _ = try output .write (line );
50- _ = try output .write ("\n " );
65+ const line = reader .interface .takeDelimiterExclusive ('\n ' ) catch | err | switch (err ) {
66+ error .EndOfStream = > return ,
67+ else = > return err ,
68+ };
69+ if (! std .mem .eql (u8 , chunk .buf , line )) {
70+ std .debug .print ("exp {s}\n got {s}\n " , .{ chunk .buf , line });
71+ @panic ("Failed to apply patch" );
72+ }
73+ try writer .interface .writeAll (line );
74+ try writer .interface .writeByte ('\n ' );
5175 },
5276 .add = > {
53- _ = try output . write (chunk .buf );
54- _ = try output . write ( " \n " );
77+ try writer . interface . writeAll (chunk .buf );
78+ try writer . interface . writeByte ( ' \n ' );
5579 },
5680 }
5781
@@ -62,7 +86,8 @@ pub fn main() !void {
6286}
6387
6488fn getLine (allocator : Allocator , file : File ) ? []u8 {
65- return file .reader ().readUntilDelimiterAlloc (allocator , '\n ' , std .math .maxInt (usize )) catch | err | switch (err ) {
89+ var buffer : [4096 ]u8 = undefined ;
90+ return file .reader (& buffer ).readUntilDelimiterAlloc (allocator , '\n ' , std .math .maxInt (usize )) catch | err | switch (err ) {
6691 error .EndOfStream = > return null ,
6792 else = > @panic ("Error" ),
6893 };
@@ -82,9 +107,9 @@ const Chunk = struct {
82107 buf : []const u8 ,
83108 };
84109
85- fn next ( allocator : Allocator , file : File ) ? Chunk {
86- while ( true ) {
87- const line = getLine ( allocator , file ) orelse return null ;
110+ fn init ( arena : std.mem. Allocator , contents : [] const u8 , pos : usize ) ? Chunk {
111+ var it = std . mem . tokenizeScalar ( u8 , contents [ pos .. ], ' \n ' );
112+ while ( it . next ()) | line | {
88113 if (std .mem .startsWith (u8 , line , "@@" )) {
89114 const end = std .mem .indexOfPosLinear (u8 , line , 3 , "@@" ).? ;
90115 const details = line [4 .. end - 2 ];
@@ -95,7 +120,7 @@ const Chunk = struct {
95120
96121 var lines : std .ArrayListUnmanaged (Line ) = .empty ;
97122 while (true ) {
98- const diff_line = getLine ( allocator , file ) orelse break ;
123+ const diff_line = it . next ( ) orelse break ;
99124 if (std .mem .startsWith (u8 , diff_line , "@@" )) break ;
100125
101126 const action : Line.Action = switch (diff_line [0 ]) {
@@ -105,16 +130,17 @@ const Chunk = struct {
105130 else = > @panic ("Bad patch file" ),
106131 };
107132
108- lines .append (allocator , .{ .action = action , .buf = diff_line [1.. ] }) catch unreachable ;
133+ lines .append (arena , .{ .action = action , .buf = diff_line [1.. ] }) catch unreachable ;
109134 }
110135
111136 return .{
112- .lines = lines .toOwnedSlice (allocator ) catch unreachable ,
137+ .lines = lines .toOwnedSlice (arena ) catch unreachable ,
113138 .src = src ,
114139 .dst = dst ,
115140 };
116141 }
117142 }
143+ return null ;
118144 }
119145
120146 fn getLineNumber (buf : []const u8 ) usize {
0 commit comments