Browse code

re_data: search/compare functions: search forward, search backwards, memcmp

Dario Rodriguez authored on 22/10/2020 21:34:45
Showing 2 changed files
... ...
@@ -1466,6 +1466,94 @@ redata_generic_genname(char *filename,char *prefix, char *postfix, char *buf, in
1466 1466
         return(name);
1467 1467
 }
1468 1468
 
1469
+long
1470
+redata_searchforward(redata_t *redata, long posini, char *str, int len)
1471
+{
1472
+        int numchunk;
1473
+        int offset;
1474
+        int avail;
1475
+        long chunkstartpos;
1476
+        rechunk_t *chunk;
1477
+        char *ptr;
1478
+        if(redata==NULL || posini<0 || (posini+len)>redata_getsize(redata) || len<0 || (str==NULL && len>0))
1479
+                return(-1); /* sanity check failed */
1480
+        if(len==0)
1481
+                return(posini); /* nothing to do, empty string is always equal */
1482
+        if(redata_getposptr(redata,posini,&numchunk,&offset)!=0)
1483
+                return(-1); /* couldn't get pos */
1484
+        chunkstartpos=posini-offset;
1485
+        for(;numchunk<redata->sizechunks
1486
+          ;chunkstartpos+=chunk->useddata,numchunk++,offset=0) {
1487
+                chunk=redata->chunks[numchunk];
1488
+                avail=chunk->useddata-offset;
1489
+                while(avail>0 && (ptr=memchr(chunk->data+offset,str[0],avail))!=NULL) {
1490
+                        offset=ptr-((char *)(chunk->data));
1491
+                        if(redata_memcmp(redata,chunkstartpos+offset,str,len)==0)
1492
+                                return(chunkstartpos+offset);
1493
+                        offset++;
1494
+                        avail=chunk->useddata-offset;
1495
+                }
1496
+        }
1497
+        return(-1); /* not found */
1498
+}
1499
+
1500
+long
1501
+redata_searchbackwards(redata_t *redata, long posini, char *str, int len)
1502
+{
1503
+        int numchunk;
1504
+        int offset;
1505
+        long chunkstartpos;
1506
+        rechunk_t *chunk;
1507
+        char *ptr;
1508
+        if(redata==NULL || posini<0 || (posini+len)>redata_getsize(redata) || len<0 || (str==NULL && len>0))
1509
+                return(-1); /* sanity check failed */
1510
+        if(len==0)
1511
+                return(posini); /* nothing to do, empty string is always equal */
1512
+        if(redata_getposptr(redata,posini,&numchunk,&offset)!=0)
1513
+                return(-1); /* couldn't get pos */
1514
+        chunkstartpos=posini-offset;
1515
+        for(offset++;numchunk>=0
1516
+          ;numchunk--
1517
+          ,offset=(numchunk>=0)?redata->chunks[numchunk]->useddata:0
1518
+          ,chunkstartpos-=(numchunk>=0)?redata->chunks[numchunk]->useddata:0) {
1519
+                chunk=redata->chunks[numchunk];
1520
+                while(offset>0 && (ptr=mymemrchr(chunk->data,str[0],offset))!=NULL) {
1521
+                        offset=ptr-((char *)(chunk->data));
1522
+                        if(redata_memcmp(redata,chunkstartpos+offset,str,len)==0)
1523
+                                return(chunkstartpos+offset);
1524
+                }
1525
+        }
1526
+        return(-1); /* not found */
1527
+}
1528
+
1529
+int
1530
+redata_memcmp(redata_t *redata, long pos, char *str, int len)
1531
+{
1532
+        int numchunk;
1533
+        int offset;
1534
+        int avail;
1535
+        int ncompared;
1536
+        rechunk_t *chunk;
1537
+        int res;
1538
+        if(redata==NULL || pos<0 || (pos+len)>redata_getsize(redata) || len<0 || (str==NULL && len>0))
1539
+                return(-1); /* sanity check failed, return "this is smaller" */
1540
+        if(len==0)
1541
+                return(0); /* nothing to do, empty string is always equal */
1542
+        if(redata_getposptr(redata,pos,&numchunk,&offset)!=0)
1543
+                return(-1); /* couldn't get pos */
1544
+        for(ncompared=0;numchunk<redata->sizechunks;numchunk++,offset=0) {
1545
+                chunk=redata->chunks[numchunk];
1546
+                avail=chunk->useddata-offset;
1547
+                avail=(avail>(len-ncompared))?(len-ncompared):avail;
1548
+                if((res=memcmp(chunk->data+offset,str+ncompared,avail))!=0 || (ncompared+avail)==len)
1549
+                        return(res); /* comparison finished */
1550
+                ncompared+=avail;
1551
+        }
1552
+        return(-1); /* not enough data in chunks */
1553
+
1554
+}
1555
+
1556
+
1469 1557
 int
1470 1558
 redata_generic_utf8len(char *ptr, int size)
1471 1559
 {
... ...
@@ -163,6 +163,11 @@ undostack_t *redata_getstack(redata_t *redata, undo_t *undo);
163 163
 
164 164
 char *redata_generic_genname(char *filename,char *prefix, char *postfix, char *buf, int bufsize);
165 165
 
166
+/* search */
167
+long redata_searchforward(redata_t *redata, long posini, char *str, int len);
168
+long redata_searchbackwards(redata_t *redata, long posini, char *str, int len);
169
+int redata_memcmp(redata_t *redata, long pos, char *str, int len);
170
+
166 171
 /* utf8 convenience functions */
167 172
 
168 173
 /* calculate the number of utf8-charaters in buffer */