77// Generates a list of offsets for ever line in the array.
88void updateOffsets (std::vector<size_t >& offsets, NSMutableArray <NSString *>* lines) {
99 offsets.clear ();
10- offsets.reserve (lines.count + 1 );
10+ offsets.reserve (lines.count + 2 );
1111 offsets.push_back (0 );
1212 size_t offset = 0 ;
1313 for (NSString * line in lines) {
14- offsets.push_back (offset += line. length );
14+ offsets.push_back (offset += [ line lengthOfBytesUsingEncoding: NSUTF8StringEncoding] );
1515 }
16+ offsets.push_back (offset);
1617}
1718
1819clang::format::FormatStyle::LanguageKind getLanguageKind (XCSourceTextBuffer* buffer) {
@@ -227,6 +228,9 @@ - (void)performCommandWithInvocation:(XCSourceEditorCommandInvocation*)invocatio
227228 continue ;
228229 }
229230
231+ // We're adding a final offset index that is the position beyond the last byte.
232+ assert (end_it + 1 != offsets.end ());
233+
230234 // We need to go one line back unless we're at the beginning of the line.
231235 if (*start_it > start) {
232236 --start_it;
@@ -237,18 +241,18 @@ - (void)performCommandWithInvocation:(XCSourceEditorCommandInvocation*)invocatio
237241
238242 const size_t start_line = std::distance (offsets.begin (), start_it);
239243 const int64_t start_column = int64_t (start) - int64_t (*start_it);
244+ assert (start_column >= 0 );
240245
241246 const size_t end_line = std::distance (offsets.begin (), end_it);
242247 const int64_t end_column = int64_t (end) - int64_t (*end_it);
243-
244- NSString * before = [[lines objectAtIndex: start_line] substringToIndex: start_column];
245- NSString * changed = [[NSString alloc ] initWithBytes: replacement.data ()
246- length: replacement.size ()
247- encoding: NSUTF8StringEncoding];
248- NSString * after = end_line >= lines.count
249- ? @" "
250- : [[lines objectAtIndex: end_line] substringFromIndex: end_column];
251- NSString * string = [@[ before, changed, after ] componentsJoinedByString: @" " ];
248+ assert (end_column >= 0 );
249+ NSData * before_line = [[lines objectAtIndex: start_line] dataUsingEncoding: NSUTF8StringEncoding];
250+ NSData * after_line = [[lines objectAtIndex: end_line] dataUsingEncoding: NSUTF8StringEncoding];
251+ NSMutableData * replacement_data = [[NSMutableData alloc ] initWithBytes: before_line.bytes length: start_column];
252+ [replacement_data appendBytes: replacement.data () length: replacement.size ()];
253+ [replacement_data appendBytes: (reinterpret_cast <const char *>(after_line.bytes) + end_column) length: (after_line.length - end_column)];
254+
255+ NSString * string = [[NSString alloc ] initWithData: replacement_data encoding: NSUTF8StringEncoding];
252256 NSMutableArray * replacements = [[NSMutableArray alloc ] init ];
253257 [string
254258 enumerateSubstringsInRange: NSMakeRange (0 , string.length)
0 commit comments