Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #ifndef SC_DEVICE_SELECTION_H
11 : #define SC_DEVICE_SELECTION_H
12 :
13 :
14 : #ifdef _MSC_VER
15 : #define _CRT_SECURE_NO_WARNINGS
16 : #endif
17 :
18 : #include <stdlib.h>
19 : #include <stdio.h>
20 : #include <string.h>
21 : #include "clcc/clew.h"
22 :
23 : #define DS_DEVICE_NAME_LENGTH 256
24 :
25 : enum ds_status
26 : {
27 : DS_SUCCESS = 0
28 : ,DS_INVALID_PROFILE = 1000
29 : ,DS_MEMORY_ERROR
30 : , DS_INVALID_PERF_EVALUATOR_TYPE
31 : , DS_INVALID_PERF_EVALUATOR
32 : , DS_PERF_EVALUATOR_ERROR
33 : , DS_FILE_ERROR
34 : , DS_UNKNOWN_DEVICE_TYPE
35 : , DS_PROFILE_FILE_ERROR
36 : , DS_SCORE_SERIALIZER_ERROR
37 : , DS_SCORE_DESERIALIZER_ERROR
38 : };
39 :
40 : // device type
41 : enum ds_device_type
42 : {
43 : DS_DEVICE_NATIVE_CPU = 0
44 : ,DS_DEVICE_OPENCL_DEVICE
45 : };
46 :
47 :
48 : struct ds_device
49 : {
50 : ds_device_type type;
51 : cl_device_id oclDeviceID;
52 : char* oclDeviceName;
53 : char* oclDriverVersion;
54 : void* score; // a pointer to the score data, the content/format is application defined
55 : };
56 :
57 : struct ds_profile
58 : {
59 : unsigned int numDevices;
60 : ds_device* devices;
61 : const char* version;
62 : };
63 :
64 : // deallocate memory used by score
65 : typedef ds_status(* ds_score_release)(void* score);
66 0 : inline ds_status releaseDSProfile(ds_profile* profile, ds_score_release sr)
67 : {
68 0 : ds_status status = DS_SUCCESS;
69 0 : if (profile != NULL)
70 : {
71 0 : if (profile->devices != NULL && sr != NULL)
72 : {
73 : unsigned int i;
74 0 : for (i = 0; i < profile->numDevices; i++)
75 : {
76 0 : free(profile->devices[i].oclDeviceName);
77 0 : free(profile->devices[i].oclDriverVersion);
78 0 : status = sr(profile->devices[i].score);
79 0 : if (status != DS_SUCCESS) break;
80 : }
81 0 : free(profile->devices);
82 : }
83 0 : free(profile);
84 : }
85 0 : return status;
86 : }
87 :
88 :
89 0 : inline ds_status initDSProfile(ds_profile** p, const char* version)
90 : {
91 : int numDevices;
92 : cl_uint numPlatforms;
93 0 : cl_platform_id* platforms = NULL;
94 0 : cl_device_id* devices = NULL;
95 0 : ds_status status = DS_SUCCESS;
96 0 : ds_profile* profile = NULL;
97 : unsigned int next;
98 : unsigned int i;
99 :
100 0 : if (p == NULL) return DS_INVALID_PROFILE;
101 :
102 0 : profile = (ds_profile*)malloc(sizeof(ds_profile));
103 0 : if (profile == NULL) return DS_MEMORY_ERROR;
104 :
105 0 : memset(profile, 0, sizeof(ds_profile));
106 :
107 0 : clGetPlatformIDs(0, NULL, &numPlatforms);
108 0 : if (numPlatforms != 0)
109 : {
110 0 : platforms = (cl_platform_id*)malloc(numPlatforms * sizeof(cl_platform_id));
111 0 : if (platforms == NULL)
112 : {
113 0 : status = DS_MEMORY_ERROR;
114 0 : goto cleanup;
115 : }
116 0 : clGetPlatformIDs(numPlatforms, platforms, NULL);
117 : }
118 :
119 0 : numDevices = 0;
120 0 : for (i = 0; i < (unsigned int)numPlatforms; i++)
121 : {
122 : cl_uint num;
123 0 : clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_ALL, 0, NULL, &num);
124 0 : numDevices += num;
125 : }
126 0 : if (numDevices != 0)
127 : {
128 0 : devices = (cl_device_id*)malloc(numDevices * sizeof(cl_device_id));
129 0 : if (devices == NULL)
130 : {
131 0 : status = DS_MEMORY_ERROR;
132 0 : goto cleanup;
133 : }
134 : }
135 :
136 0 : profile->numDevices = numDevices + 1; // +1 to numDevices to include the native CPU
137 0 : profile->devices = (ds_device*)malloc(profile->numDevices * sizeof(ds_device));
138 0 : if (profile->devices == NULL)
139 : {
140 0 : profile->numDevices = 0;
141 0 : status = DS_MEMORY_ERROR;
142 0 : goto cleanup;
143 : }
144 0 : memset(profile->devices, 0, profile->numDevices * sizeof(ds_device));
145 :
146 0 : next = 0;
147 0 : for (i = 0; i < (unsigned int)numPlatforms; i++)
148 : {
149 : cl_uint num;
150 : unsigned j;
151 0 : clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_ALL, numDevices, devices, &num);
152 0 : for (j = 0; j < num; j++, next++)
153 : {
154 : char buffer[DS_DEVICE_NAME_LENGTH];
155 : size_t length;
156 :
157 0 : profile->devices[next].type = DS_DEVICE_OPENCL_DEVICE;
158 0 : profile->devices[next].oclDeviceID = devices[j];
159 :
160 0 : clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DEVICE_NAME
161 0 : , DS_DEVICE_NAME_LENGTH, &buffer, NULL);
162 0 : length = strlen(buffer);
163 0 : profile->devices[next].oclDeviceName = (char*)malloc(length + 1);
164 0 : memcpy(profile->devices[next].oclDeviceName, buffer, length + 1);
165 :
166 0 : clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DRIVER_VERSION
167 0 : , DS_DEVICE_NAME_LENGTH, &buffer, NULL);
168 0 : length = strlen(buffer);
169 0 : profile->devices[next].oclDriverVersion = (char*)malloc(length + 1);
170 0 : memcpy(profile->devices[next].oclDriverVersion, buffer, length + 1);
171 : }
172 : }
173 0 : profile->devices[next].type = DS_DEVICE_NATIVE_CPU;
174 0 : profile->version = version;
175 :
176 : cleanup:
177 0 : if (platforms) free(platforms);
178 0 : if (devices) free(devices);
179 0 : if (status == DS_SUCCESS)
180 : {
181 0 : *p = profile;
182 : }
183 : else
184 : {
185 0 : if (profile)
186 : {
187 0 : if (profile->devices) free(profile->devices);
188 0 : free(profile);
189 : }
190 : }
191 0 : return status;
192 : }
193 :
194 : // Pointer to a function that calculates the score of a device (ex: device->score)
195 : // update the data size of score. The encoding and the format of the score data
196 : // is implementation defined. The function should return DS_SUCCESS if there's no error to be reported.
197 : typedef ds_status(* ds_perf_evaluator)(ds_device* device, void* data);
198 :
199 : typedef enum {
200 : DS_EVALUATE_ALL
201 : , DS_EVALUATE_NEW_ONLY
202 : } ds_evaluation_type;
203 :
204 0 : inline ds_status profileDevices(ds_profile* profile, const ds_evaluation_type type,
205 : ds_perf_evaluator evaluator, void* evaluatorData, unsigned int* numUpdates)
206 : {
207 0 : ds_status status = DS_SUCCESS;
208 : unsigned int i;
209 0 : unsigned int updates = 0;
210 :
211 0 : if (profile == NULL)
212 : {
213 0 : return DS_INVALID_PROFILE;
214 : }
215 0 : if (evaluator == NULL)
216 : {
217 0 : return DS_INVALID_PERF_EVALUATOR;
218 : }
219 :
220 0 : for (i = 0; i < profile->numDevices; i++)
221 : {
222 : ds_status evaluatorStatus;
223 :
224 0 : switch (type)
225 : {
226 : case DS_EVALUATE_NEW_ONLY:
227 0 : if (profile->devices[i].score != NULL) break;
228 : // else fall through
229 : case DS_EVALUATE_ALL:
230 0 : evaluatorStatus = evaluator(profile->devices + i, evaluatorData);
231 0 : if (evaluatorStatus != DS_SUCCESS)
232 : {
233 0 : status = evaluatorStatus;
234 0 : return status;
235 : }
236 0 : updates++;
237 0 : break;
238 : default:
239 0 : return DS_INVALID_PERF_EVALUATOR_TYPE;
240 : break;
241 : };
242 : }
243 0 : if (numUpdates) *numUpdates = updates;
244 0 : return status;
245 : }
246 :
247 :
248 : #define DS_TAG_VERSION "<version>"
249 : #define DS_TAG_VERSION_END "</version>"
250 : #define DS_TAG_DEVICE "<device>"
251 : #define DS_TAG_DEVICE_END "</device>"
252 : #define DS_TAG_SCORE "<score>"
253 : #define DS_TAG_SCORE_END "</score>"
254 : #define DS_TAG_DEVICE_TYPE "<type>"
255 : #define DS_TAG_DEVICE_TYPE_END "</type>"
256 : #define DS_TAG_DEVICE_NAME "<name>"
257 : #define DS_TAG_DEVICE_NAME_END "</name>"
258 : #define DS_TAG_DEVICE_DRIVER_VERSION "<driver>"
259 : #define DS_TAG_DEVICE_DRIVER_VERSION_END "</driver>"
260 :
261 : #define DS_DEVICE_NATIVE_CPU_STRING "native_cpu"
262 :
263 : typedef ds_status(* ds_score_serializer)(ds_device* device, void** serializedScore, unsigned int* serializedScoreSize);
264 0 : inline ds_status writeProfileToFile(ds_profile* profile, ds_score_serializer serializer, const char* file)
265 : {
266 0 : ds_status status = DS_SUCCESS;
267 0 : FILE* profileFile = NULL;
268 :
269 :
270 0 : if (profile == NULL) return DS_INVALID_PROFILE;
271 :
272 0 : profileFile = fopen(file, "wb");
273 0 : if (profileFile == NULL)
274 : {
275 0 : status = DS_FILE_ERROR;
276 : }
277 : else
278 : {
279 : unsigned int i;
280 :
281 : // write version string
282 0 : fwrite(DS_TAG_VERSION, sizeof(char), strlen(DS_TAG_VERSION), profileFile);
283 0 : fwrite(profile->version, sizeof(char), strlen(profile->version), profileFile);
284 0 : fwrite(DS_TAG_VERSION_END, sizeof(char), strlen(DS_TAG_VERSION_END), profileFile);
285 0 : fwrite("\n", sizeof(char), 1, profileFile);
286 :
287 0 : for (i = 0; i < profile->numDevices && status == DS_SUCCESS; i++)
288 : {
289 : void* serializedScore;
290 : unsigned int serializedScoreSize;
291 :
292 0 : fwrite(DS_TAG_DEVICE, sizeof(char), strlen(DS_TAG_DEVICE), profileFile);
293 :
294 0 : fwrite(DS_TAG_DEVICE_TYPE, sizeof(char), strlen(DS_TAG_DEVICE_TYPE), profileFile);
295 0 : fwrite(&profile->devices[i].type, sizeof(ds_device_type), 1, profileFile);
296 0 : fwrite(DS_TAG_DEVICE_TYPE_END, sizeof(char), strlen(DS_TAG_DEVICE_TYPE_END), profileFile);
297 :
298 0 : switch (profile->devices[i].type)
299 : {
300 : case DS_DEVICE_NATIVE_CPU:
301 : {
302 : // There's no need to emit a device name for the native CPU device.
303 : /*
304 : fwrite(DS_TAG_DEVICE_NAME, sizeof(char), strlen(DS_TAG_DEVICE_NAME), profileFile);
305 : fwrite(DS_DEVICE_NATIVE_CPU_STRING,sizeof(char),strlen(DS_DEVICE_NATIVE_CPU_STRING), profileFile);
306 : fwrite(DS_TAG_DEVICE_NAME_END, sizeof(char), strlen(DS_TAG_DEVICE_NAME_END), profileFile);
307 : */
308 : }
309 0 : break;
310 : case DS_DEVICE_OPENCL_DEVICE:
311 : {
312 0 : fwrite(DS_TAG_DEVICE_NAME, sizeof(char), strlen(DS_TAG_DEVICE_NAME), profileFile);
313 0 : fwrite(profile->devices[i].oclDeviceName, sizeof(char), strlen(profile->devices[i].oclDeviceName), profileFile);
314 0 : fwrite(DS_TAG_DEVICE_NAME_END, sizeof(char), strlen(DS_TAG_DEVICE_NAME_END), profileFile);
315 :
316 0 : fwrite(DS_TAG_DEVICE_DRIVER_VERSION, sizeof(char), strlen(DS_TAG_DEVICE_DRIVER_VERSION), profileFile);
317 0 : fwrite(profile->devices[i].oclDriverVersion, sizeof(char), strlen(profile->devices[i].oclDriverVersion), profileFile);
318 0 : fwrite(DS_TAG_DEVICE_DRIVER_VERSION_END, sizeof(char), strlen(DS_TAG_DEVICE_DRIVER_VERSION_END), profileFile);
319 : }
320 0 : break;
321 : default:
322 0 : status = DS_UNKNOWN_DEVICE_TYPE;
323 0 : break;
324 : };
325 :
326 0 : fwrite(DS_TAG_SCORE, sizeof(char), strlen(DS_TAG_SCORE), profileFile);
327 0 : status = serializer(profile->devices + i, &serializedScore, &serializedScoreSize);
328 0 : if (status == DS_SUCCESS && serializedScore != NULL && serializedScoreSize > 0)
329 : {
330 0 : fwrite(serializedScore, sizeof(char), serializedScoreSize, profileFile);
331 0 : free(serializedScore);
332 : }
333 0 : fwrite(DS_TAG_SCORE_END, sizeof(char), strlen(DS_TAG_SCORE_END), profileFile);
334 0 : fwrite(DS_TAG_DEVICE_END, sizeof(char), strlen(DS_TAG_DEVICE_END), profileFile);
335 0 : fwrite("\n", sizeof(char), 1, profileFile);
336 : }
337 0 : fclose(profileFile);
338 : }
339 0 : return status;
340 : }
341 :
342 :
343 0 : inline ds_status readProFile(const char* fileName, char** content, size_t* contentSize)
344 : {
345 0 : FILE* input = NULL;
346 0 : size_t size = 0;
347 0 : char* binary = NULL;
348 0 : long pos = -1;
349 :
350 0 : *contentSize = 0;
351 0 : *content = NULL;
352 :
353 0 : input = fopen(fileName, "rb");
354 0 : if (input == NULL)
355 : {
356 0 : return DS_FILE_ERROR;
357 : }
358 :
359 0 : fseek(input, 0L, SEEK_END);
360 0 : pos = ftell(input);
361 0 : if (pos < 0)
362 : {
363 0 : fclose(input);
364 0 : return DS_FILE_ERROR;
365 : }
366 :
367 0 : size = pos;
368 0 : rewind(input);
369 0 : binary = (char*)malloc(size);
370 0 : if (binary == NULL)
371 : {
372 0 : fclose(input);
373 0 : return DS_FILE_ERROR;
374 : }
375 0 : size_t bytesRead = fread(binary, sizeof(char), size, input);
376 : (void) bytesRead; // avoid warning
377 0 : fclose(input);
378 :
379 0 : *contentSize = size;
380 0 : *content = binary;
381 0 : return DS_SUCCESS;
382 : }
383 :
384 :
385 0 : inline const char* findString(const char* contentStart, const char* contentEnd, const char* string)
386 : {
387 : size_t stringLength;
388 : const char* currentPosition;
389 : const char* found;
390 0 : found = NULL;
391 0 : stringLength = strlen(string);
392 0 : currentPosition = contentStart;
393 0 : for (currentPosition = contentStart; currentPosition < contentEnd; currentPosition++)
394 : {
395 0 : if (*currentPosition == string[0])
396 : {
397 0 : if (currentPosition + stringLength < contentEnd)
398 : {
399 0 : if (strncmp(currentPosition, string, stringLength) == 0)
400 : {
401 0 : found = currentPosition;
402 0 : break;
403 : }
404 : }
405 : }
406 : }
407 0 : return found;
408 : }
409 :
410 :
411 : typedef ds_status(* ds_score_deserializer)(ds_device* device, const unsigned char* serializedScore, unsigned int serializedScoreSize);
412 0 : inline ds_status readProfileFromFile(ds_profile* profile, ds_score_deserializer deserializer, const char* file)
413 : {
414 :
415 0 : ds_status status = DS_SUCCESS;
416 0 : char* contentStart = NULL;
417 0 : const char* contentEnd = NULL;
418 : size_t contentSize;
419 :
420 0 : if (profile == NULL) return DS_INVALID_PROFILE;
421 :
422 0 : status = readProFile(file, &contentStart, &contentSize);
423 0 : if (status == DS_SUCCESS)
424 : {
425 : const char* currentPosition;
426 : const char* dataStart;
427 : const char* dataEnd;
428 : size_t versionStringLength;
429 :
430 0 : contentEnd = contentStart + contentSize;
431 0 : currentPosition = contentStart;
432 :
433 :
434 : // parse the version string
435 0 : dataStart = findString(currentPosition, contentEnd, DS_TAG_VERSION);
436 0 : if (dataStart == NULL)
437 : {
438 0 : status = DS_PROFILE_FILE_ERROR;
439 0 : goto cleanup;
440 : }
441 0 : dataStart += strlen(DS_TAG_VERSION);
442 :
443 0 : dataEnd = findString(dataStart, contentEnd, DS_TAG_VERSION_END);
444 0 : if (dataEnd == NULL)
445 : {
446 0 : status = DS_PROFILE_FILE_ERROR;
447 0 : goto cleanup;
448 : }
449 :
450 0 : versionStringLength = strlen(profile->version);
451 0 : if (versionStringLength != static_cast<size_t>(dataEnd - dataStart)
452 0 : || strncmp(profile->version, dataStart, versionStringLength) != 0)
453 : {
454 : // version mismatch
455 0 : status = DS_PROFILE_FILE_ERROR;
456 0 : goto cleanup;
457 : }
458 0 : currentPosition = dataEnd + strlen(DS_TAG_VERSION_END);
459 :
460 : // parse the device information
461 : while (true)
462 : {
463 : unsigned int i;
464 :
465 : const char* deviceTypeStart;
466 : const char* deviceTypeEnd;
467 : ds_device_type deviceType;
468 :
469 : const char* deviceNameStart;
470 : const char* deviceNameEnd;
471 :
472 : const char* deviceScoreStart;
473 : const char* deviceScoreEnd;
474 :
475 : const char* deviceDriverStart;
476 : const char* deviceDriverEnd;
477 :
478 0 : dataStart = findString(currentPosition, contentEnd, DS_TAG_DEVICE);
479 0 : if (dataStart == NULL)
480 : {
481 : // nothing useful remain, quit...
482 0 : break;
483 : }
484 0 : dataStart += strlen(DS_TAG_DEVICE);
485 0 : dataEnd = findString(dataStart, contentEnd, DS_TAG_DEVICE_END);
486 0 : if (dataEnd == NULL)
487 : {
488 0 : status = DS_PROFILE_FILE_ERROR;
489 0 : goto cleanup;
490 : }
491 :
492 : // parse the device type
493 0 : deviceTypeStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_TYPE);
494 0 : if (deviceTypeStart == NULL)
495 : {
496 0 : status = DS_PROFILE_FILE_ERROR;
497 0 : goto cleanup;
498 : }
499 0 : deviceTypeStart += strlen(DS_TAG_DEVICE_TYPE);
500 0 : deviceTypeEnd = findString(deviceTypeStart, contentEnd, DS_TAG_DEVICE_TYPE_END);
501 0 : if (deviceTypeEnd == NULL)
502 : {
503 0 : status = DS_PROFILE_FILE_ERROR;
504 0 : goto cleanup;
505 : }
506 0 : memcpy(&deviceType, deviceTypeStart, sizeof(ds_device_type));
507 :
508 :
509 : // parse the device name
510 0 : if (deviceType == DS_DEVICE_OPENCL_DEVICE)
511 : {
512 :
513 0 : deviceNameStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_NAME);
514 0 : if (deviceNameStart == NULL)
515 : {
516 0 : status = DS_PROFILE_FILE_ERROR;
517 0 : goto cleanup;
518 : }
519 0 : deviceNameStart += strlen(DS_TAG_DEVICE_NAME);
520 0 : deviceNameEnd = findString(deviceNameStart, contentEnd, DS_TAG_DEVICE_NAME_END);
521 0 : if (deviceNameEnd == NULL)
522 : {
523 0 : status = DS_PROFILE_FILE_ERROR;
524 0 : goto cleanup;
525 : }
526 :
527 :
528 0 : deviceDriverStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_DRIVER_VERSION);
529 0 : if (deviceDriverStart == NULL)
530 : {
531 0 : status = DS_PROFILE_FILE_ERROR;
532 0 : goto cleanup;
533 : }
534 0 : deviceDriverStart += strlen(DS_TAG_DEVICE_DRIVER_VERSION);
535 0 : deviceDriverEnd = findString(deviceDriverStart, contentEnd, DS_TAG_DEVICE_DRIVER_VERSION_END);
536 0 : if (deviceDriverEnd == NULL)
537 : {
538 0 : status = DS_PROFILE_FILE_ERROR;
539 0 : goto cleanup;
540 : }
541 :
542 :
543 : // check if this device is on the system
544 0 : for (i = 0; i < profile->numDevices; i++)
545 : {
546 0 : if (profile->devices[i].type == DS_DEVICE_OPENCL_DEVICE)
547 : {
548 : size_t actualDeviceNameLength;
549 : size_t driverVersionLength;
550 :
551 0 : actualDeviceNameLength = strlen(profile->devices[i].oclDeviceName);
552 0 : driverVersionLength = strlen(profile->devices[i].oclDriverVersion);
553 0 : if (actualDeviceNameLength == static_cast<size_t>(deviceNameEnd - deviceNameStart)
554 0 : && driverVersionLength == static_cast<size_t>(deviceDriverEnd - deviceDriverStart)
555 0 : && strncmp(profile->devices[i].oclDeviceName, deviceNameStart, actualDeviceNameLength) == 0
556 0 : && strncmp(profile->devices[i].oclDriverVersion, deviceDriverStart, driverVersionLength) == 0)
557 : {
558 :
559 0 : deviceScoreStart = findString(dataStart, contentEnd, DS_TAG_SCORE);
560 0 : if (deviceScoreStart == NULL)
561 : {
562 0 : status = DS_PROFILE_FILE_ERROR;
563 0 : goto cleanup;
564 : }
565 0 : deviceScoreStart += strlen(DS_TAG_SCORE);
566 0 : deviceScoreEnd = findString(deviceScoreStart, contentEnd, DS_TAG_SCORE_END);
567 0 : status = deserializer(profile->devices + i, (const unsigned char*)deviceScoreStart, deviceScoreEnd - deviceScoreStart);
568 0 : if (status != DS_SUCCESS)
569 : {
570 0 : goto cleanup;
571 : }
572 : }
573 : }
574 : }
575 :
576 : }
577 0 : else if (deviceType == DS_DEVICE_NATIVE_CPU)
578 : {
579 0 : for (i = 0; i < profile->numDevices; i++)
580 : {
581 0 : if (profile->devices[i].type == DS_DEVICE_NATIVE_CPU)
582 : {
583 0 : deviceScoreStart = findString(dataStart, contentEnd, DS_TAG_SCORE);
584 0 : if (deviceScoreStart == NULL)
585 : {
586 0 : status = DS_PROFILE_FILE_ERROR;
587 0 : goto cleanup;
588 : }
589 0 : deviceScoreStart += strlen(DS_TAG_SCORE);
590 0 : deviceScoreEnd = findString(deviceScoreStart, contentEnd, DS_TAG_SCORE_END);
591 0 : status = deserializer(profile->devices + i, (const unsigned char*)deviceScoreStart, deviceScoreEnd - deviceScoreStart);
592 0 : if (status != DS_SUCCESS)
593 : {
594 0 : goto cleanup;
595 : }
596 : }
597 : }
598 : }
599 :
600 : // skip over the current one to find the next device
601 0 : currentPosition = dataEnd + strlen(DS_TAG_DEVICE_END);
602 0 : }
603 : }
604 : cleanup:
605 0 : if (contentStart != NULL) free(contentStart);
606 0 : return status;
607 : }
608 :
609 : inline ds_status getNumDeviceWithEmptyScore(ds_profile* profile, unsigned int* num)
610 : {
611 : unsigned int i;
612 : if (profile == NULL || num == NULL) return DS_MEMORY_ERROR;
613 : *num = 0;
614 : for (i = 0; i < profile->numDevices; i++)
615 : {
616 : if (profile->devices[i].score == NULL)
617 : {
618 : (*num)++;
619 : }
620 : }
621 : return DS_SUCCESS;
622 : }
623 :
624 : #endif
625 :
626 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|