Browse code

unsaved_loadappend: implement loading of A(dd) and D(el) registers

Dario Rodriguez authored on 14/03/2019 22:37:34
Showing 3 changed files
... ...
@@ -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);