source: trunk/src/@xmltree/private/xml_findstr.c @ 820

Last change on this file since 820 was 820, checked in by sommeria, 9 years ago

xmltree_updated

File size: 3.2 KB
Line 
1#include "mex.h"
2
3/*
4    Differences with matlab built-in findstr:
5        - allows to search only the n first occurences of a pattern
6        - allows to search only in a substring (given an index of the beginning)
7   
8    Matlab hack:
9        - doesn't use mxGetString to prevent a copy of the string.
10        - assumes Matlab stores strings as unsigned short (Unicode 16 bits)
11          matrix.h: typedef uint16_T mxChar;
12          (that's the case for Matlab 5.* and 6.* but Matlab 4.* stores strings
13           as double)
14*/
15
16/* Comment the following line to use standard mxGetString (slower) */
17#define __HACK_MXCHAR__
18
19void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
20
21    unsigned int i, j, stext, spattern, nbmatch = 0, ind = 1, occur = 0, nboccur = 0;
22#ifdef __HACK_MXCHAR__
23    unsigned short int *text = NULL, *pattern = NULL;
24#else
25    char *text = NULL, *pattern = NULL;
26#endif
27    unsigned int *k = NULL;
28    mxArray *out = NULL;
29   
30        /* Check for proper number of arguments. */
31    if ((nrhs == 0) || (nrhs == 1))
32            mexErrMsgTxt("Not enough input arguments.");
33    else if (nrhs > 4)
34            mexErrMsgTxt("Too many input arguments.");
35    else if (nlhs > 1)
36        mexErrMsgTxt("Too many output arguments.");
37   
38    /* The input TEXT must be a string */
39        if (!mxIsChar(prhs[0]))
40            mexErrMsgTxt("Inputs must be character arrays.");
41        stext = mxGetM(prhs[0]) * mxGetN(prhs[0]);
42#ifdef __HACK_MXCHAR__
43        text = mxGetData(prhs[0]);
44#else
45    text = mxCalloc(stext+1, sizeof(char));
46    mxGetString(prhs[0], text, stext+1);
47#endif
48       
49    /* The input PATTERN must be a string */
50        if (!mxIsChar(prhs[1]))
51                mexErrMsgTxt("Inputs must be character arrays.");
52    spattern = mxGetM(prhs[1]) * mxGetN(prhs[1]);
53#ifdef __HACK_MXCHAR__
54        pattern = mxGetData(prhs[1]);
55#else
56    pattern = mxCalloc(spattern+1, sizeof(char));
57        mxGetString(prhs[1], pattern, spattern+1);
58#endif
59
60        /* The input INDEX must be an integer */
61        if (nrhs > 2) {
62            if ((!mxIsNumeric(prhs[2]) || (mxGetM(prhs[2]) * mxGetN(prhs[2]) !=  1)))
63                mexErrMsgTxt("Index input must be an integer.");
64            ind = (unsigned int)mxGetScalar(prhs[2]);
65            if (ind < 1)
66                mexErrMsgTxt("Index must be greater than 1.");
67        }
68       
69        /* The input OCCUR must be an integer */
70        if (nrhs == 4) {
71            if ((!mxIsNumeric(prhs[3]) || (mxGetM(prhs[3]) * mxGetN(prhs[3]) !=  1)))
72                mexErrMsgTxt("Index input must be an integer.");
73            nboccur = (unsigned int)mxGetScalar(prhs[3]);
74        }
75       
76        /* Find pattern in text */
77    for (i=ind-1;i<stext;i++) {
78        for (j=0;j<spattern && i+j<stext;j++) {
79            if (pattern[j] == text[i+j]) {
80                if (j == spattern-1) {
81                    nbmatch += 1;
82                    k = mxRealloc(k,nbmatch*sizeof(unsigned int));
83                    k[nbmatch-1] = i+1;
84                    if (++occur == nboccur) i = stext;
85                }
86            }
87            else break;
88        }
89    }
90   
91    /* Allocate output */
92    out = mxCreateDoubleMatrix((nbmatch) ? 1:0, nbmatch, mxREAL);
93   
94    /* Copy index array into output */
95    for (i=0;i<nbmatch;i++)
96        mxGetPr(out)[i] = (double)k[i];
97   
98    /* Assign pointer to output */
99    plhs[0] = out;
100   
101    /* Free memory */
102    if (k) mxFree(k);
103}
Note: See TracBrowser for help on using the repository browser.