277
* This represents a "file", which is an array of "lines".
278
*/
279
struct image {
280
- char *buf;
281
- size_t len;
280
+ struct strbuf buf;
281
struct line *line;
282
size_t line_nr, line_alloc;
283
};
285
-#define IMAGE_INIT { 0 }
284
+#define IMAGE_INIT { \
285
+ .buf = STRBUF_INIT, \
286
+}
287
288
static void image_init(struct image *image)
289
{
293
294
static void image_clear(struct image *image)
295
{
295
- free(image->buf);
296
+ strbuf_release(&image->buf);
297
free(image->line);
298
image_init(image);
299
}
330
const char *cp, *ep;
331
332
image_clear(image);
332
- image->buf = buf;
333
- image->len = len;
333
+ strbuf_attach(&image->buf, buf, len, len + 1);
334
335
if (!prepare_linetable)
336
return;
337
338
- ep = image->buf + image->len;
339
- cp = image->buf;
338
+ ep = image->buf.buf + image->buf.len;
339
+ cp = image->buf.buf;
340
while (cp < ep) {
341
const char *next;
342
for (next = cp; next < ep && *next != '\n'; next++)
350
351
static void image_remove_first_line(struct image *img)
352
{
353
- img->buf += img->line[0].len;
354
- img->len -= img->line[0].len;
353
+ strbuf_remove(&img->buf, 0, img->line[0].len);
354
img->line_nr--;
355
if (img->line_nr)
356
MOVE_ARRAY(img->line, img->line + 1, img->line_nr);
358
359
static void image_remove_last_line(struct image *img)
360
{
362
- img->len -= img->line[--img->line_nr].len;
361
+ size_t last_line_len = img->line[img->line_nr - 1].len;
362
+ strbuf_setlen(&img->buf, img->buf.len - last_line_len);
363
+ img->line_nr--;
364
}
365
366
/* fmt must contain _one_ %s and no other substitution */
2309
2310
/*
2311
* Update the preimage, and the common lines in postimage,
2311
- * from buffer buf of length len. If postlen is 0 the postimage
2312
- * is updated in place, otherwise it's updated on a new buffer
2313
- * of length postlen
2312
+ * from buffer buf of length len.
2313
*/
2315
-
2314
static void update_pre_post_images(struct image *preimage,
2315
struct image *postimage,
2318
- char *buf,
2319
- size_t len, size_t postlen)
2316
+ char *buf, size_t len)
2317
{
2321
- int i, ctx, reduced;
2322
- char *new_buf, *old_buf, *fixed;
2318
struct image fixed_preimage = IMAGE_INIT;
2319
+ size_t insert_pos = 0;
2320
+ int i, ctx, reduced;
2321
+ const char *fixed;
2322
2323
/*
2324
* Update the preimage with whitespace fixes. Note that we
2326
* free "oldlines".
2327
*/
2328
image_prepare(&fixed_preimage, buf, len, 1);
2331
- assert(postlen
2332
- ? fixed_preimage.line_nr == preimage->line_nr
2333
- : fixed_preimage.line_nr <= preimage->line_nr);
2329
for (i = 0; i < fixed_preimage.line_nr; i++)
2330
fixed_preimage.line[i].flag = preimage->line[i].flag;
2336
- free(preimage->line);
2331
+ image_clear(preimage);
2332
*preimage = fixed_preimage;
2333
+ fixed = preimage->buf.buf;
2334
2335
/*
2340
- * Adjust the common context lines in postimage. This can be
2341
- * done in-place when we are shrinking it with whitespace
2342
- * fixing, but needs a new buffer when ignoring whitespace or
2343
- * expanding leading tabs to spaces.
2344
- *
2345
- * We trust the caller to tell us if the update can be done
2346
- * in place (postlen==0) or not.
2336
+ * Adjust the common context lines in postimage.
2337
*/
2348
- old_buf = postimage->buf;
2349
- if (postlen)
2350
- new_buf = postimage->buf = xmalloc(postlen);
2351
- else
2352
- new_buf = old_buf;
2353
- fixed = preimage->buf;
2354
-
2338
for (i = reduced = ctx = 0; i < postimage->line_nr; i++) {
2339
size_t l_len = postimage->line[i].len;
2340
+
2341
if (!(postimage->line[i].flag & LINE_COMMON)) {
2342
/* an added line -- no counterparts in preimage */
2359
- memmove(new_buf, old_buf, l_len);
2360
- old_buf += l_len;
2361
- new_buf += l_len;
2343
+ insert_pos += l_len;
2344
continue;
2345
}
2346
2365
- /* a common context -- skip it in the original postimage */
2366
- old_buf += l_len;
2367
-
2347
/* and find the corresponding one in the fixed preimage */
2348
while (ctx < preimage->line_nr &&
2349
!(preimage->line[ctx].flag & LINE_COMMON)) {
2362
2363
/* and copy it in, while fixing the line length */
2364
l_len = preimage->line[ctx].len;
2386
- memcpy(new_buf, fixed, l_len);
2387
- new_buf += l_len;
2365
+ strbuf_splice(&postimage->buf, insert_pos, postimage->line[i].len,
2366
+ fixed, l_len);
2367
+ insert_pos += l_len;
2368
fixed += l_len;
2369
postimage->line[i].len = l_len;
2370
ctx++;
2371
}
2372
2393
- if (postlen
2394
- ? postlen < new_buf - postimage->buf
2395
- : postimage->len < new_buf - postimage->buf)
2396
- BUG("caller miscounted postlen: asked %d, orig = %d, used = %d",
2397
- (int)postlen, (int) postimage->len, (int)(new_buf - postimage->buf));
2398
-
2373
/* Fix the length of the whole thing */
2400
- postimage->len = new_buf - postimage->buf;
2374
postimage->line_nr -= reduced;
2375
}
2376
2420
int i;
2421
size_t imgoff = 0;
2422
size_t preoff = 0;
2450
- size_t postlen = postimage->len;
2423
size_t extra_chars;
2424
char *buf;
2425
char *preimage_eof;
2432
size_t prelen = preimage->line[i].len;
2433
size_t imglen = img->line[current_lno+i].len;
2434
2463
- if (!fuzzy_matchlines(img->buf + current + imgoff, imglen,
2464
- preimage->buf + preoff, prelen))
2435
+ if (!fuzzy_matchlines(img->buf.buf + current + imgoff, imglen,
2436
+ preimage->buf.buf + preoff, prelen))
2437
return 0;
2466
- if (preimage->line[i].flag & LINE_COMMON)
2467
- postlen += imglen - prelen;
2438
imgoff += imglen;
2439
preoff += prelen;
2440
}
2450
* are whitespace characters. (This can only happen if
2451
* we are removing blank lines at the end of the file.)
2452
*/
2483
- buf = preimage_eof = preimage->buf + preoff;
2453
+ buf = preimage_eof = preimage->buf.buf + preoff;
2454
for ( ; i < preimage->line_nr; i++)
2455
preoff += preimage->line[i].len;
2486
- preimage_end = preimage->buf + preoff;
2456
+ preimage_end = preimage->buf.buf + preoff;
2457
for ( ; buf < preimage_end; buf++)
2458
if (!isspace(*buf))
2459
return 0;
2467
*/
2468
extra_chars = preimage_end - preimage_eof;
2469
strbuf_init(&fixed, imgoff + extra_chars);
2500
- strbuf_add(&fixed, img->buf + current, imgoff);
2470
+ strbuf_add(&fixed, img->buf.buf + current, imgoff);
2471
strbuf_add(&fixed, preimage_eof, extra_chars);
2472
fixed_buf = strbuf_detach(&fixed, &fixed_len);
2473
update_pre_post_images(preimage, postimage,
2504
- fixed_buf, fixed_len, postlen);
2474
+ fixed_buf, fixed_len);
2475
return 1;
2476
}
2477
2487
int i;
2488
const char *orig, *target;
2489
struct strbuf fixed = STRBUF_INIT;
2520
- size_t postlen;
2490
+ char *fixed_buf;
2491
+ size_t fixed_len;
2492
int preimage_limit;
2493
int ret;
2494
2544
* exactly.
2545
*/
2546
if ((match_end
2576
- ? (current + preimage->len == img->len)
2577
- : (current + preimage->len <= img->len)) &&
2578
- !memcmp(img->buf + current, preimage->buf, preimage->len)) {
2547
+ ? (current + preimage->buf.len == img->buf.len)
2548
+ : (current + preimage->buf.len <= img->buf.len)) &&
2549
+ !memcmp(img->buf.buf + current, preimage->buf.buf, preimage->buf.len)) {
2550
ret = 1;
2551
goto out;
2552
}
2560
*/
2561
const char *buf, *buf_end;
2562
2592
- buf = preimage->buf;
2563
+ buf = preimage->buf.buf;
2564
buf_end = buf;
2565
for (i = 0; i < preimage_limit; i++)
2566
buf_end += preimage->line[i].len;
2605
* fixed.
2606
*/
2607
2637
- /* First count added lines in postimage */
2638
- postlen = 0;
2639
- for (i = 0; i < postimage->line_nr; i++) {
2640
- if (!(postimage->line[i].flag & LINE_COMMON))
2641
- postlen += postimage->line[i].len;
2642
- }
2643
-
2608
/*
2609
* The preimage may extend beyond the end of the file,
2610
* but in this loop we will only handle the part of the
2611
* preimage that falls within the file.
2612
*/
2649
- strbuf_grow(&fixed, preimage->len + 1);
2650
- orig = preimage->buf;
2651
- target = img->buf + current;
2613
+ strbuf_grow(&fixed, preimage->buf.len + 1);
2614
+ orig = preimage->buf.buf;
2615
+ target = img->buf.buf + current;
2616
for (i = 0; i < preimage_limit; i++) {
2617
size_t oldlen = preimage->line[i].len;
2618
size_t tgtlen = img->line[current_lno + i].len;
2641
!memcmp(tgtfix.buf, fixed.buf + fixstart,
2642
fixed.len - fixstart));
2643
2680
- /* Add the length if this is common with the postimage */
2681
- if (preimage->line[i].flag & LINE_COMMON)
2682
- postlen += tgtfix.len;
2683
-
2644
strbuf_release(&tgtfix);
2645
if (!match) {
2646
ret = 0;
2682
* has whitespace breakages unfixed, and fixing them makes the
2683
* hunk match. Update the context lines in the postimage.
2684
*/
2725
- if (postlen < postimage->len)
2726
- postlen = 0;
2685
+ fixed_buf = strbuf_detach(&fixed, &fixed_len);
2686
update_pre_post_images(preimage, postimage,
2728
- fixed.buf, fixed.len, postlen);
2687
+ fixed_buf, fixed_len);
2688
2689
ret = 1;
2690
2798
*/
2799
int i, nr;
2800
size_t remove_count, insert_count, applied_at = 0;
2801
+ size_t result_alloc;
2802
char *result;
2803
int preimage_limit;
2804
2821
remove_count = 0;
2822
for (i = 0; i < preimage_limit; i++)
2823
remove_count += img->line[applied_pos + i].len;
2864
- insert_count = postimage->len;
2824
+ insert_count = postimage->buf.len;
2825
2826
/* Adjust the contents */
2867
- result = xmalloc(st_add3(st_sub(img->len, remove_count), insert_count, 1));
2868
- memcpy(result, img->buf, applied_at);
2869
- memcpy(result + applied_at, postimage->buf, postimage->len);
2870
- memcpy(result + applied_at + postimage->len,
2871
- img->buf + (applied_at + remove_count),
2872
- img->len - (applied_at + remove_count));
2873
- free(img->buf);
2874
- img->buf = result;
2875
- img->len += insert_count - remove_count;
2876
- result[img->len] = '\0';
2827
+ result_alloc = st_add3(st_sub(img->buf.len, remove_count), insert_count, 1);
2828
+ result = xmalloc(result_alloc);
2829
+ memcpy(result, img->buf.buf, applied_at);
2830
+ memcpy(result + applied_at, postimage->buf.buf, postimage->buf.len);
2831
+ memcpy(result + applied_at + postimage->buf.len,
2832
+ img->buf.buf + (applied_at + remove_count),
2833
+ img->buf.len - (applied_at + remove_count));
2834
+ strbuf_attach(&img->buf, result, postimage->buf.len + img->buf.len - remove_count,
2835
+ result_alloc);
2836
2837
/* Adjust the line table */
2838
nr = img->line_nr + postimage->line_nr - preimage_limit;
3013
match_end = !state->unidiff_zero && !trailing;
3014
3015
pos = frag->newpos ? (frag->newpos - 1) : 0;
3057
- preimage.buf = oldlines;
3058
- preimage.len = old - oldlines;
3059
- postimage.buf = newlines.buf;
3060
- postimage.len = newlines.len;
3016
+ strbuf_add(&preimage.buf, oldlines, old - oldlines);
3017
+ strbuf_swap(&postimage.buf, &newlines);
3018
3019
for (;;) {
3020
3102
out:
3103
free(oldlines);
3104
strbuf_release(&newlines);
3148
- free(preimage.line);
3149
- free(postimage.line);
3105
+ image_clear(&preimage);
3106
+ image_clear(&postimage);
3107
3108
return (applied_pos < 0);
3109
}
3133
}
3134
switch (fragment->binary_patch_method) {
3135
case BINARY_DELTA_DEFLATED:
3179
- dst = patch_delta(img->buf, img->len, fragment->patch,
3136
+ dst = patch_delta(img->buf.buf, img->buf.len, fragment->patch,
3137
fragment->size, &len);
3138
if (!dst)
3139
return -1;
3140
image_clear(img);
3184
- img->buf = dst;
3185
- img->len = len;
3141
+ strbuf_attach(&img->buf, dst, len, len + 1);
3142
return 0;
3143
case BINARY_LITERAL_DEFLATED:
3144
image_clear(img);
3189
- img->len = fragment->size;
3190
- img->buf = xmemdupz(fragment->patch, img->len);
3145
+ strbuf_add(&img->buf, fragment->patch, fragment->size);
3146
return 0;
3147
}
3148
return -1;
3178
* See if the old one matches what the patch
3179
* applies to.
3180
*/
3226
- hash_object_file(the_hash_algo, img->buf, img->len, OBJ_BLOB,
3227
- &oid);
3181
+ hash_object_file(the_hash_algo, img->buf.buf, img->buf.len,
3182
+ OBJ_BLOB, &oid);
3183
if (strcmp(oid_to_hex(&oid), patch->old_oid_prefix))
3184
return error(_("the patch applies to '%s' (%s), "
3185
"which does not match the "
3188
}
3189
else {
3190
/* Otherwise, the old one must be empty. */
3236
- if (img->len)
3191
+ if (img->buf.len)
3192
return error(_("the patch applies to an empty "
3193
"'%s' but it is not empty"), name);
3194
}
3212
"'%s' cannot be read"),
3213
patch->new_oid_prefix, name);
3214
image_clear(img);
3260
- img->buf = result;
3261
- img->len = size;
3215
+ strbuf_attach(&img->buf, result, size, size + 1);
3216
} else {
3217
/*
3218
* We have verified buf matches the preimage;
3224
name);
3225
3226
/* verify that the result matches */
3273
- hash_object_file(the_hash_algo, img->buf, img->len, OBJ_BLOB,
3227
+ hash_object_file(the_hash_algo, img->buf.buf, img->buf.len, OBJ_BLOB,
3228
&oid);
3229
if (strcmp(oid_to_hex(&oid), patch->new_oid_prefix))
3230
return error(_("binary patch to '%s' creates incorrect result (expecting %s, got %s)"),
3494
{
3495
unsigned long size;
3496
enum object_type type;
3497
+ char *data;
3498
3499
image_clear(image);
3500
3546
- image->buf = repo_read_object_file(the_repository, result_id, &type,
3547
- &size);
3548
- if (!image->buf || type != OBJ_BLOB)
3501
+ data = repo_read_object_file(the_repository, result_id, &type, &size);
3502
+ if (!data || type != OBJ_BLOB)
3503
die("unable to read blob object %s", oid_to_hex(result_id));
3550
- image->len = size;
3504
+ strbuf_attach(&image->buf, data, size, size + 1);
3505
3506
return 0;
3507
}
3543
return -1;
3544
}
3545
image_clear(image);
3592
- image->buf = result.ptr;
3593
- image->len = result.size;
3546
+ strbuf_attach(&image->buf, result.ptr, result.size, result.size);
3547
3548
return status;
3549
}
3630
return -1;
3631
}
3632
/* post_oid is theirs */
3680
- write_object_file(tmp_image.buf, tmp_image.len, OBJ_BLOB, &post_oid);
3633
+ write_object_file(tmp_image.buf.buf, tmp_image.buf.len, OBJ_BLOB, &post_oid);
3634
image_clear(&tmp_image);
3635
3636
/* our_oid is ours */
3643
return error(_("cannot read the current contents of '%s'"),
3644
patch->old_name);
3645
}
3693
- write_object_file(tmp_image.buf, tmp_image.len, OBJ_BLOB, &our_oid);
3646
+ write_object_file(tmp_image.buf.buf, tmp_image.buf.len, OBJ_BLOB, &our_oid);
3647
image_clear(&tmp_image);
3648
3649
/* in-core three-way merge between post and our using pre as base */
3696
return -1;
3697
}
3698
}
3746
- patch->result = image.buf;
3747
- patch->resultsize = image.len;
3699
+ patch->result = strbuf_detach(&image.buf, &patch->resultsize);
3700
add_to_fn_table(state, patch);
3701
free(image.line);
3702