1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <ctype.h>
5 #include <errno.h>
6 
7 #include "mex.h"
8 
9 #ifdef MX_API_VER
10 #if MX_API_VER < 0x07030000
11 typedef int mwIndex;
12 #endif
13 #endif
14 #ifndef max
15 #define max(x,y) (((x)>(y))?(x):(y))
16 #endif
17 #ifndef min
18 #define min(x,y) (((x)<(y))?(x):(y))
19 #endif
20 
exit_with_help()21 void exit_with_help()
22 {
23 	mexPrintf(
24 	"Usage: [label_vector, instance_matrix] = libsvmread('filename');\n"
25 	);
26 }
27 
fake_answer(int nlhs,mxArray * plhs[])28 static void fake_answer(int nlhs, mxArray *plhs[])
29 {
30 	int i;
31 	for(i=0;i<nlhs;i++)
32 		plhs[i] = mxCreateDoubleMatrix(0, 0, mxREAL);
33 }
34 
35 static char *line;
36 static int max_line_len;
37 
readline(FILE * input)38 static char* readline(FILE *input)
39 {
40 	int len;
41 
42 	if(fgets(line,max_line_len,input) == NULL)
43 		return NULL;
44 
45 	while(strrchr(line,'\n') == NULL)
46 	{
47 		max_line_len *= 2;
48 		line = (char *) realloc(line, max_line_len);
49 		len = (int) strlen(line);
50 		if(fgets(line+len,max_line_len-len,input) == NULL)
51 			break;
52 	}
53 	return line;
54 }
55 
56 // read in a problem (in libsvm format)
read_problem(const char * filename,int nlhs,mxArray * plhs[])57 void read_problem(const char *filename, int nlhs, mxArray *plhs[])
58 {
59 	int max_index, min_index, inst_max_index;
60 	size_t elements, k, i, l=0;
61 	FILE *fp = fopen(filename,"r");
62 	char *endptr;
63 	mwIndex *ir, *jc;
64 	double *labels, *samples;
65 
66 	if(fp == NULL)
67 	{
68 		mexPrintf("can't open input file %s\n",filename);
69 		fake_answer(nlhs, plhs);
70 		return;
71 	}
72 
73 	max_line_len = 1024;
74 	line = (char *) malloc(max_line_len*sizeof(char));
75 
76 	max_index = 0;
77 	min_index = 1; // our index starts from 1
78 	elements = 0;
79 	while(readline(fp) != NULL)
80 	{
81 		char *idx, *val;
82 		// features
83 		int index = 0;
84 
85 		inst_max_index = -1; // strtol gives 0 if wrong format, and precomputed kernel has <index> start from 0
86 		strtok(line," \t"); // label
87 		while (1)
88 		{
89 			idx = strtok(NULL,":"); // index:value
90 			val = strtok(NULL," \t");
91 			if(val == NULL)
92 				break;
93 
94 			errno = 0;
95 			index = (int) strtol(idx,&endptr,10);
96 			if(endptr == idx || errno != 0 || *endptr != '\0' || index <= inst_max_index)
97 			{
98 				mexPrintf("Wrong input format at line %d\n",l+1);
99 				fake_answer(nlhs, plhs);
100 				return;
101 			}
102 			else
103 				inst_max_index = index;
104 
105 			min_index = min(min_index, index);
106 			elements++;
107 		}
108 		max_index = max(max_index, inst_max_index);
109 		l++;
110 	}
111 	rewind(fp);
112 
113 	// y
114 	plhs[0] = mxCreateDoubleMatrix(l, 1, mxREAL);
115 	// x^T
116 	if (min_index <= 0)
117 		plhs[1] = mxCreateSparse(max_index-min_index+1, l, elements, mxREAL);
118 	else
119 		plhs[1] = mxCreateSparse(max_index, l, elements, mxREAL);
120 
121 	labels = mxGetPr(plhs[0]);
122 	samples = mxGetPr(plhs[1]);
123 	ir = mxGetIr(plhs[1]);
124 	jc = mxGetJc(plhs[1]);
125 
126 	k=0;
127 	for(i=0;i<l;i++)
128 	{
129 		char *idx, *val, *label;
130 		jc[i] = k;
131 
132 		readline(fp);
133 
134 		label = strtok(line," \t\n");
135 		if(label == NULL)
136 		{
137 			mexPrintf("Empty line at line %d\n",i+1);
138 			fake_answer(nlhs, plhs);
139 			return;
140 		}
141 		labels[i] = strtod(label,&endptr);
142 		if(endptr == label || *endptr != '\0')
143 		{
144 			mexPrintf("Wrong input format at line %d\n",i+1);
145 			fake_answer(nlhs, plhs);
146 			return;
147 		}
148 
149 		// features
150 		while(1)
151 		{
152 			idx = strtok(NULL,":");
153 			val = strtok(NULL," \t");
154 			if(val == NULL)
155 				break;
156 
157 			ir[k] = (mwIndex) (strtol(idx,&endptr,10) - min_index); // precomputed kernel has <index> start from 0
158 
159 			errno = 0;
160 			samples[k] = strtod(val,&endptr);
161 			if (endptr == val || errno != 0 || (*endptr != '\0' && !isspace(*endptr)))
162 			{
163 				mexPrintf("Wrong input format at line %d\n",i+1);
164 				fake_answer(nlhs, plhs);
165 				return;
166 			}
167 			++k;
168 		}
169 	}
170 	jc[l] = k;
171 
172 	fclose(fp);
173 	free(line);
174 
175 	{
176 		mxArray *rhs[1], *lhs[1];
177 		rhs[0] = plhs[1];
178 		if(mexCallMATLAB(1, lhs, 1, rhs, "transpose"))
179 		{
180 			mexPrintf("Error: cannot transpose problem\n");
181 			fake_answer(nlhs, plhs);
182 			return;
183 		}
184 		plhs[1] = lhs[0];
185 	}
186 }
187 
mexFunction(int nlhs,mxArray * plhs[],int nrhs,const mxArray * prhs[])188 void mexFunction( int nlhs, mxArray *plhs[],
189 		int nrhs, const mxArray *prhs[] )
190 {
191 	char filename[256];
192 
193 	if(nrhs != 1 || nlhs != 2)
194 	{
195 		exit_with_help();
196 		fake_answer(nlhs, plhs);
197 		return;
198 	}
199 
200 	mxGetString(prhs[0], filename, mxGetN(prhs[0]) + 1);
201 
202 	if(filename == NULL)
203 	{
204 		mexPrintf("Error: filename is NULL\n");
205 		return;
206 	}
207 
208 	read_problem(filename, nlhs, plhs);
209 
210 	return;
211 }
212 
213