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

Last change on this file since 925 was 925, checked in by sommeria, 8 years ago

xmltree updated

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