... | ... |
@@ -36,6 +36,9 @@ static int redata_unsaved_check_gen(redata_t *redata, char *filename); |
36 | 36 |
static char *unsaved_genname(char *filename, char *buf, int bufsize); |
37 | 37 |
static char *securesave_genname(char *filename, char *buf, int bufsize); |
38 | 38 |
static char *genname(char *filename,char *prefix, char *postfix, char *buf, int bufsize); |
39 |
+static char *ptr_getlong(char *ptr,char *endptr,long *data); |
|
40 |
+static char *ptr_getchar(char *ptr,char *endptr,char *data); |
|
41 |
+static char *ptr_searchendchar(char *ptr, char *endptr, char endchar, char **endcharpos); |
|
39 | 42 |
|
40 | 43 |
redata_t * |
41 | 44 |
redata_init(void) |
... | ... |
@@ -57,6 +60,8 @@ redata_init(void) |
57 | 60 |
/* unsaved */ |
58 | 61 |
redata->filename[0]='\0'; |
59 | 62 |
redata->unsavedfd=-1; |
63 |
+ redata->unsaved.sizebuf=redata->unsaved.usedbuf=0; |
|
64 |
+ redata->unsaved.lastsize=0; |
|
60 | 65 |
/* all done */ |
61 | 66 |
return(redata); |
62 | 67 |
} |
... | ... |
@@ -472,7 +477,7 @@ int |
472 | 477 |
redata_unsaved_check(redata_t *redata, char *filename) |
473 | 478 |
{ |
474 | 479 |
int fd; |
475 |
- if((fd=redata_unsaved_check(redata,filename))==-1) |
|
480 |
+ if((fd=redata_unsaved_check_gen(redata,filename))==-1) |
|
476 | 481 |
return(-1); /* check failed */ |
477 | 482 |
close(fd),fd=-1; |
478 | 483 |
return(0); |
... | ... |
@@ -519,6 +524,7 @@ redata_unsaved_trunc(redata_t *redata) |
519 | 524 |
return(0); |
520 | 525 |
} |
521 | 526 |
|
527 |
+ |
|
522 | 528 |
int |
523 | 529 |
redata_unsaved_loadappend(redata_t *redata) |
524 | 530 |
{ |
... | ... |
@@ -528,7 +534,12 @@ redata_unsaved_loadappend(redata_t *redata) |
528 | 534 |
long headerhashsize; |
529 | 535 |
char *newptr; |
530 | 536 |
long nread,lim; |
531 |
- if((fd=redata_unsaved_check(redata,redata->filename))==-1) |
|
537 |
+ char *ptr,*endptr,*aux,*bufptr; |
|
538 |
+ char actioncode; |
|
539 |
+ long pos; |
|
540 |
+ char endcode; |
|
541 |
+ int flag_multipart; |
|
542 |
+ if((fd=redata_unsaved_check_gen(redata,redata->filename))==-1) |
|
532 | 543 |
return(-1); /* check failed */ |
533 | 544 |
if(fstat(fd,&statbuf)!=0 || !S_ISREG(statbuf.st_mode)) { |
534 | 545 |
close(fd),fd=-1; |
... | ... |
@@ -556,7 +567,50 @@ redata_unsaved_loadappend(redata_t *redata) |
556 | 567 |
} |
557 | 568 |
close(fd),fd=-1; |
558 | 569 |
/* process unsaved data */ |
570 |
+ endptr=redata->unsaved.buf+redata->unsaved.usedbuf; |
|
571 |
+ for(ptr=redata->unsaved.buf;ptr<endptr;) { |
|
572 |
+ if((ptr=ptr_getchar(ptr,endptr,&actioncode))==NULL) |
|
573 |
+ return(-1); /* no space for action char */ |
|
574 |
+ /* multipart example: A10+$aj$%$% >> insert "aj$" into pos 10 */ |
|
575 |
+ if(actioncode=='A') { |
|
576 |
+ ptr=ptr_getlong(ptr,endptr,&pos); |
|
577 |
+ do { |
|
578 |
+ flag_multipart=0; |
|
579 |
+ ptr=ptr_getchar(ptr,endptr,&endcode); |
|
580 |
+ if(ptr!=NULL && endcode=='+') { |
|
581 |
+ flag_multipart=1; |
|
582 |
+ ptr=ptr_getchar(ptr,endptr,&endcode); |
|
583 |
+ } |
|
584 |
+ bufptr=ptr; |
|
585 |
+ ptr=ptr_searchendchar(ptr,endptr,endcode,&aux); |
|
586 |
+ if(ptr==NULL || pos<0 || pos>redata_getused(redata)) |
|
587 |
+ return(-1); /* malformed register */ |
|
588 |
+ redata_op_add(redata,pos,bufptr,aux-bufptr,NULL); |
|
589 |
+ pos+=aux-bufptr; |
|
590 |
+ } while(flag_multipart); |
|
591 |
+ } else if(actioncode=='D') { |
|
592 |
+ ptr=ptr_getlong(ptr,endptr,&pos); |
|
593 |
+ do { |
|
594 |
+ flag_multipart=0; |
|
595 |
+ ptr=ptr_getchar(ptr,endptr,&endcode); |
|
596 |
+ if(ptr!=NULL && endcode=='+') { |
|
597 |
+ flag_multipart=1; |
|
598 |
+ ptr=ptr_getchar(ptr,endptr,&endcode); |
|
599 |
+ } |
|
600 |
+ bufptr=ptr; |
|
601 |
+ ptr=ptr_searchendchar(ptr,endptr,endcode,&aux); |
|
602 |
+ if(ptr==NULL || pos<0 || (pos+(aux-bufptr))>redata_getused(redata)) |
|
603 |
+ return(-1); /* malformed register */ |
|
604 |
+ if(redata_data_compare(redata,pos,bufptr,aux-bufptr)!=0) |
|
605 |
+ return(-1); /* corrupted data */ |
|
606 |
+ redata_op_del(redata,pos,aux-bufptr,NULL); |
|
607 |
+ } while(flag_multipart); |
|
608 |
+ } else if(actioncode=='M') { |
|
559 | 609 |
#warning TODO |
610 |
+ } else { |
|
611 |
+ return(-1); /* corrupted undobuf */ |
|
612 |
+ } |
|
613 |
+ } |
|
560 | 614 |
return(-1); |
561 | 615 |
} |
562 | 616 |
|
... | ... |
@@ -1025,6 +1079,31 @@ redata_op_redo(redata_t *redata) |
1025 | 1079 |
return(-1); |
1026 | 1080 |
} |
1027 | 1081 |
|
1082 |
+int |
|
1083 |
+redata_data_compare(redata_t *redata, long cmppos, char *buf, long buflen) |
|
1084 |
+{ |
|
1085 |
+ int chunkno; |
|
1086 |
+ long pos; |
|
1087 |
+ long compared; |
|
1088 |
+ long n; |
|
1089 |
+ int res; |
|
1090 |
+ if(redata==NULL || pos<0 || buf==NULL || buflen<0 |
|
1091 |
+ || cmppos>redata_getused(redata) |
|
1092 |
+ || (cmppos+buflen)>redata_getused(redata)) |
|
1093 |
+ return(-1); /* sanity check failed */ |
|
1094 |
+ if(redata_getposptr(redata,cmppos,&chunkno,&pos)==-1) |
|
1095 |
+ return(-1); /* invalid pos */ |
|
1096 |
+ for(compared=0,n=0;compared<buflen && chunkno<redata->sizechunks;chunkno++,pos=0,compared+=n) { |
|
1097 |
+ n=redata->chunks[chunkno]->useddata-pos; |
|
1098 |
+ n=(n<0)?0:((compared+n)>buflen)?(buflen-compared):n; |
|
1099 |
+ if((res=memcmp(redata->chunks[chunkno]->data+pos,buf+compared,n))!=0) |
|
1100 |
+ return(res); |
|
1101 |
+ } |
|
1102 |
+ if(compared<buflen) |
|
1103 |
+ return(1); |
|
1104 |
+ return(0); |
|
1105 |
+} |
|
1106 |
+ |
|
1028 | 1107 |
int |
1029 | 1108 |
redata_hash(redata_t *redata, char *resbuf129bytes) |
1030 | 1109 |
{ |
... | ... |
@@ -1159,4 +1238,49 @@ genname(char *filename,char *prefix, char *postfix, char *buf, int bufsize) |
1159 | 1238 |
return(name); |
1160 | 1239 |
} |
1161 | 1240 |
|
1241 |
+static char * |
|
1242 |
+ptr_getlong(char *ptr,char *endptr,long *data) |
|
1243 |
+{ |
|
1244 |
+ long l,s; |
|
1245 |
+ if(ptr==NULL || endptr==NULL || ptr>endptr) |
|
1246 |
+ return(NULL); |
|
1247 |
+ s=1; |
|
1248 |
+ if(ptr<endptr && *ptr=='-') { |
|
1249 |
+ s=-1; |
|
1250 |
+ ptr++; |
|
1251 |
+ } |
|
1252 |
+ for(l=0;ptr<endptr && *ptr>='0' && *ptr<='9';ptr++) { |
|
1253 |
+ l*=10; |
|
1254 |
+ l+=(*ptr-'0'); |
|
1255 |
+ } |
|
1256 |
+ l*=s; |
|
1257 |
+ if(data!=NULL) |
|
1258 |
+ *data=l; |
|
1259 |
+ return(ptr); |
|
1260 |
+} |
|
1261 |
+ |
|
1262 |
+ |
|
1263 |
+static char * |
|
1264 |
+ptr_getchar(char *ptr,char *endptr,char *data) |
|
1265 |
+{ |
|
1266 |
+ if(ptr==NULL || endptr==NULL || ptr>endptr) |
|
1267 |
+ return(NULL); |
|
1268 |
+ if(data!=NULL) |
|
1269 |
+ *data=*ptr; |
|
1270 |
+ ptr++; |
|
1271 |
+ return(ptr); |
|
1272 |
+} |
|
1273 |
+ |
|
1274 |
+static char * |
|
1275 |
+ptr_searchendchar(char *ptr, char *endptr, char endchar, char **endcharpos) |
|
1276 |
+{ |
|
1277 |
+ char *aux; |
|
1278 |
+ if(ptr==NULL || endptr==NULL || ptr>endptr) |
|
1279 |
+ return(NULL); |
|
1280 |
+ if((aux=memchr(ptr,endchar,endptr-ptr))==NULL) |
|
1281 |
+ return(NULL); |
|
1282 |
+ if(endcharpos!=NULL) |
|
1283 |
+ *endcharpos=aux; |
|
1284 |
+ return(aux+1); |
|
1285 |
+} |
|
1162 | 1286 |
|
... | ... |
@@ -114,6 +114,7 @@ int redata_op_move(redata_t *redata, long posorig, long size, long posdest, undo |
114 | 114 |
int redata_op_undo(redata_t *redata); |
115 | 115 |
int redata_op_redo(redata_t *redata); |
116 | 116 |
|
117 |
+int redata_data_compare(redata_t *redata, long pos, char *buf, long buflen); |
|
117 | 118 |
|
118 | 119 |
int redata_hash(redata_t *redata, char *resbuf129bytes); |
119 | 120 |
int redata_filehash(redata_t *redata, char *filename, char *resbuf129bytes); |
... | ... |
@@ -47,7 +47,7 @@ main(int argc, char *argv[]) |
47 | 47 |
{"newfile_32768",test_newfile,PREFIX "FILE", NULL, 32768, 0}, |
48 | 48 |
{"newfile_32769",test_newfile,PREFIX "FILE", NULL, 32769, 0}, |
49 | 49 |
{"newfile_131072",test_newfile,PREFIX "FILE", NULL, 131072, 0}, |
50 |
- {"testedit_add",test_edit,PREFIX "EDIT", "A,0,$Testing add$",0,0}, |
|
50 |
+ {"testedit_add",test_edit,PREFIX "EDIT", "A0$Testing add$",0,0}, |
|
51 | 51 |
}; |
52 | 52 |
redata_t *redata; |
53 | 53 |
int i; |
... | ... |
@@ -173,9 +173,8 @@ fprintf(stderr,"\ntest_edit(%s%s%s,%s%s%s,%i,%i);\nResult: ",(filename!=NULL)?"\ |
173 | 173 |
} |
174 | 174 |
if(k!=0) redata_save(redata,"test.pre"); |
175 | 175 |
if(*ptr=='A') { |
176 |
- /* A,<insertpos>,<endchar>,<text><endchar> */ |
|
176 |
+ /* A<insertpos><endchar><text><endchar> */ |
|
177 | 177 |
ptr++; |
178 |
- ptr+=(*ptr==',')?1:0; |
|
179 | 178 |
errno=0; |
180 | 179 |
l=(int)strtol(ptr,&ptr,10); |
181 | 180 |
if(errno!=0 || l<0 || l>cursize) { |
... | ... |
@@ -183,7 +182,6 @@ if(k!=0) redata_save(redata,"test.pre"); |
183 | 182 |
free(mem),mem=NULL; |
184 | 183 |
return("test_edit(): error parsing position"); |
185 | 184 |
} |
186 |
- ptr+=(*ptr==',')?1:0; |
|
187 | 185 |
endcode=*ptr; |
188 | 186 |
ptr+=(*ptr!='\0')?1:0; |
189 | 187 |
ptrend=strchr(ptr,endcode); |