00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include <io.h>
00047 #include <fcntl.h>
00048 #include <sys/stat.h>
00049 #include <string.h>
00050 #include <stdarg.h>
00051 #include <time.h>
00052 #include <errno.h>
00053 #include <sys/nutdebug.h>
00054 #include <sys/event.h>
00055
00056 #include <gorp/perci.h>
00057
00062
00063
00064
00071 void PerCiDump(FILE *stream, char *path)
00072 {
00073 #ifdef NUTDEBUG
00074 int fd;
00075 int got;
00076 perci_fast_reclen_t i;
00077 perci_fast_reclen_t ll;
00078 perci_recnum_t recnum;
00079 perci_reclen_t reclen;
00080 uint8_t *recbuf;
00081
00082 fd = _open(path, _O_RDWR | _O_BINARY);
00083 if (fd == -1) {
00084 fprintf(stream, "Error %d opening %s\n", errno, path);
00085 return;
00086 } else {
00087 fprintf(stream, "Dump %ld bytes in %s\n", _filelength(fd), path);
00088 recbuf = malloc(PERCI_DATASIZE);
00089 for (recnum = 0;; recnum++) {
00090 got = _read(fd, &reclen, sizeof(perci_reclen_t));
00091 if (got <= 0) {
00092 break;
00093 }
00094 fprintf(stream, "%03u %03u ", recnum, (unsigned int)reclen);
00095 got = _read(fd, recbuf, PERCI_DATASIZE);
00096 for (i = 0, ll = 0; i < (perci_fast_reclen_t) got && i <= (perci_fast_reclen_t) reclen; i++) {
00097 if (recbuf[i] < ' ') {
00098 ll += 2;
00099 if (recbuf[i] == '\n') {
00100 fputs("\\n", stream);
00101 }
00102 else if (recbuf[i] == '\r') {
00103 fputs("\\r", stream);
00104 }
00105 else if (recbuf[i] == '\t') {
00106 fputs("\\t", stream);
00107 } else {
00108 fprintf(stream, "\\x%02x", recbuf[i]);
00109 ll += 2;
00110 }
00111 } else {
00112 fputc(recbuf[i], stream);
00113 ll++;
00114 }
00115 if (ll > 80) {
00116 fprintf(stream, "...");
00117 break;
00118 }
00119 }
00120 fputc('\n', stream);
00121 }
00122 _close(fd);
00123 free(recbuf);
00124 }
00125 #endif
00126 }
00127
00151 int PerCiInit(char *path, int recs)
00152 {
00153 int fd;
00154 int i;
00155 PERCI_RECORD *rec;
00156
00157
00158 NUTASSERT(path != NULL);
00159 NUTASSERT(recs >= 2);
00160
00161 fd = _open(path, _O_RDWR | _O_CREAT | _O_TRUNC | _O_BINARY);
00162 if (fd == -1) {
00163 return -1;
00164 }
00165 rec = calloc(PERCI_RECSIZE, 1);
00166 if (rec) {
00167 for (i = 0; i < recs; i++) {
00168 _write(fd, rec, PERCI_RECSIZE);
00169 }
00170 _write(fd, rec, sizeof(perci_reclen_t));
00171 free(rec);
00172 }
00173 _close(fd);
00174
00175 return 0;
00176 }
00177
00202 PERCI_WRITER *PerCiOpen(char *path)
00203 {
00204 uint_fast8_t ok = 0;
00205 PERCI_WRITER *writer;
00206 perci_reclen_t reclen;
00207
00208
00209 NUTASSERT(path != NULL);
00210
00211
00212 writer = calloc(1, sizeof(PERCI_WRITER));
00213 if (writer) {
00214
00215
00216 writer->pcw_fd = _open(path, _O_RDWR | _O_BINARY);
00217 if (writer->pcw_fd != -1) {
00218
00219
00220 writer->pcw_size = _filelength(writer->pcw_fd);
00221 if (writer->pcw_size >= 2 * PERCI_RECSIZE + sizeof(perci_reclen_t)) {
00222 writer->pcw_size -= sizeof(perci_reclen_t);
00223
00224
00225
00226
00227 _seek(writer->pcw_fd, 0, SEEK_SET);
00228 for (writer->pcw_recnum = 0; writer->pcw_recnum < PERCI_MAX_RECORDS; writer->pcw_recnum++) {
00229
00230 if (_read(writer->pcw_fd, &reclen, sizeof(perci_reclen_t)) != sizeof(perci_reclen_t)) {
00231
00232 break;
00233 }
00234
00235
00236 if (reclen < PERCI_DATASIZE) {
00237
00238 writer->pcw_rec.pcd_len = reclen;
00239 if (reclen && _read(writer->pcw_fd, writer->pcw_rec.pcd_data, reclen) != reclen) {
00240 break;
00241 }
00242 NutEventPost(&writer->pcw_mutex);
00243 ok = 1;
00244 break;
00245 }
00246
00247 _seek(writer->pcw_fd, PERCI_DATASIZE, SEEK_CUR);
00248 }
00249 }
00250 }
00251 }
00252
00253 if (!ok && writer) {
00254 if (writer->pcw_fd != -1) {
00255 _close(writer->pcw_fd);
00256 }
00257 free(writer);
00258 writer = NULL;
00259 }
00260 return writer;
00261 }
00262
00269 void PerCiFlush(PERCI_WRITER * writer)
00270 {
00271
00272 NUTASSERT(writer != NULL);
00273 NUTASSERT(writer->pcw_fd != -1);
00274
00275 _seek(writer->pcw_fd, writer->pcw_recnum * PERCI_RECSIZE, SEEK_SET);
00276 _write(writer->pcw_fd, &writer->pcw_rec, sizeof(perci_reclen_t) + writer->pcw_rec.pcd_len);
00277 }
00278
00285 void PerCiClose(PERCI_WRITER * writer)
00286 {
00287
00288 NUTASSERT(writer != NULL);
00289
00290 if (writer->pcw_rec.pcd_len) {
00291 PerCiFlush(writer);
00292 }
00293 _close(writer->pcw_fd);
00294 free(writer);
00295 }
00296
00305 int PerCiWrite(PERCI_WRITER * writer, CONST char *data, int len)
00306 {
00307 perci_fast_reclen_t cnt = 0;
00308 perci_fast_reclen_t num;
00309 perci_fast_reclen_t reclen;
00310
00311
00312 NUTASSERT(writer != NULL);
00313 NUTASSERT(writer->pcw_fd != -1);
00314 NUTASSERT(writer->pcw_rec.pcd_len <= PERCI_DATASIZE);
00315
00316 NutEventWait(&writer->pcw_mutex, NUT_WAIT_INFINITE);
00317 while ((perci_fast_reclen_t) len > cnt) {
00318
00319 reclen = (perci_fast_reclen_t) writer->pcw_rec.pcd_len;
00320 num = (perci_fast_reclen_t) len - cnt;
00321 if (num > PERCI_DATASIZE - reclen) {
00322 num = PERCI_DATASIZE - reclen;
00323 }
00324
00325 memcpy(&writer->pcw_rec.pcd_data[reclen], data, num);
00326 writer->pcw_rec.pcd_len += num;
00327 cnt += num;
00328 data += num;
00329
00330
00331
00332
00333
00334
00335 if (writer->pcw_rec.pcd_len == PERCI_DATASIZE) {
00336 _seek(writer->pcw_fd, writer->pcw_recnum * PERCI_RECSIZE, SEEK_SET);
00337 if (_write(writer->pcw_fd, &writer->pcw_rec, sizeof(PERCI_RECORD)) != sizeof(PERCI_RECORD)) {
00338 NutEventPost(&writer->pcw_mutex);
00339 return -1;
00340 }
00341 writer->pcw_rec.pcd_len = 0;
00342 writer->pcw_recnum++;
00343
00344 if (writer->pcw_recnum * PERCI_RECSIZE >= writer->pcw_size) {
00345 writer->pcw_recnum = 0;
00346 _seek(writer->pcw_fd, 0, SEEK_SET);
00347 if (_write(writer->pcw_fd, &writer->pcw_rec.pcd_len, sizeof(perci_reclen_t)) != sizeof(perci_reclen_t)) {
00348 NutEventPost(&writer->pcw_mutex);
00349 return -1;
00350 }
00351 }
00352 }
00353 }
00354 NutEventPost(&writer->pcw_mutex);
00355 return cnt;
00356 }
00357
00372 int PerCiWriteVarList(PERCI_WRITER * writer, CONST char *fmt, va_list ap)
00373 {
00374 int cnt;
00375 char *line;
00376
00377
00378 NUTASSERT(fmt != NULL);
00379
00380 line = malloc(PERCI_DATASIZE);
00381 if (line) {
00382
00383 cnt = vsprintf(line, fmt, ap);
00384 NUTASSERT(cnt < PERCI_DATASIZE);
00385 cnt = PerCiWrite(writer, line, strlen(line));
00386 free(line);
00387 } else {
00388 cnt = -1;
00389 }
00390 return cnt;
00391 }
00392
00393
00404 int PerCiWriteFormat(PERCI_WRITER * writer, CONST char *fmt, ...)
00405 {
00406 int rc;
00407 va_list ap;
00408
00409
00410 NUTASSERT(fmt != NULL);
00411
00412 va_start(ap, fmt);
00413 rc = PerCiWriteVarList(writer, fmt, ap);
00414 va_end(ap);
00415
00416 return rc;
00417 }
00418
00431 static perci_fast_reclen_t FindNextData(PERCI_WRITER * writer, perci_fast_recnum_t * recnum)
00432 {
00433 perci_reclen_t reclen;
00434 long pos;
00435 int got;
00436
00437
00438 NUTASSERT(writer != NULL);
00439
00440 NutEventWait(&writer->pcw_mutex, NUT_WAIT_INFINITE);
00441 pos = *recnum * PERCI_RECSIZE;
00442 for (;;) {
00443
00444
00445 if (pos >= writer->pcw_size) {
00446 pos = 0;
00447 *recnum = 0;
00448 }
00449
00450
00451 if (*recnum == writer->pcw_recnum) {
00452 reclen = writer->pcw_rec.pcd_len;
00453 break;
00454 }
00455
00456
00457 _seek(writer->pcw_fd, pos, SEEK_SET);
00458 got = _read(writer->pcw_fd, &reclen, sizeof(perci_reclen_t));
00459 if (got == sizeof(perci_reclen_t) && reclen) {
00460 break;
00461 }
00462
00463
00464 pos += PERCI_RECSIZE;
00465 (*recnum)++;
00466 }
00467 NutEventPost(&writer->pcw_mutex);
00468 return reclen;
00469 }
00470
00490 PERCI_READER *PerCiAttachReader(PERCI_WRITER * writer)
00491 {
00492 PERCI_READER *reader;
00493
00494
00495 NUTASSERT(writer != NULL);
00496
00497 reader = malloc(sizeof(PERCI_READER));
00498 reader->pcr_cil = writer;
00499 reader->pcr_recpos = 0;
00500
00501
00502 reader->pcr_recnum = writer->pcw_recnum + 1;
00503 reader->pcr_reclen = FindNextData(writer, &reader->pcr_recnum);
00504
00505 return reader;
00506 }
00507
00514 void PerCiDetachReader(PERCI_READER * reader)
00515 {
00516
00517 NUTASSERT(reader != NULL);
00518 free(reader);
00519 }
00520
00532 int PerCiRead(PERCI_READER * reader, char *data, int len)
00533 {
00534 int cnt = 0;
00535 perci_fast_reclen_t num;
00536 int got;
00537
00538
00539 NUTASSERT(reader != NULL);
00540
00541
00542
00543
00544 while (len > cnt) {
00545
00546 num = len - cnt;
00547 if (num > reader->pcr_reclen - reader->pcr_recpos) {
00548 num = reader->pcr_reclen - reader->pcr_recpos;
00549 }
00550
00551
00552 if (reader->pcr_recnum == reader->pcr_cil->pcw_recnum) {
00553 if (num) {
00554
00555 memcpy(data, &reader->pcr_cil->pcw_rec.pcd_data[reader->pcr_recpos], num);
00556 data += num;
00557 cnt += num;
00558 reader->pcr_recpos += num;
00559 } else {
00560
00561 break;
00562 }
00563 }
00564
00565 else {
00566
00567 if (num) {
00568 got = _read(reader->pcr_cil->pcw_fd, data, num);
00569 if (got != num) {
00570 break;
00571 }
00572 data += num;
00573 cnt += num;
00574 reader->pcr_recpos += num;
00575 } else {
00576
00577 reader->pcr_recnum++;
00578 reader->pcr_recpos = 0;
00579
00580 reader->pcr_reclen = FindNextData(reader->pcr_cil, &reader->pcr_recnum);
00581 if (reader->pcr_reclen == 0) {
00582
00583 break;
00584 }
00585 }
00586 }
00587 }
00588 return cnt;
00589 }
00590
00602 int PerCiReadLine(PERCI_READER * reader, char *line, int len)
00603 {
00604 int cnt = 0;
00605 char *cp = line;
00606
00607
00608 NUTASSERT(reader != NULL);
00609 NUTASSERT(line != NULL);
00610
00611 while (cnt < len) {
00612 if (PerCiRead(reader, cp, 1) != 1) {
00613 break;
00614 }
00615 cnt++;
00616 if (*cp++ == '\n') {
00617 break;
00618 }
00619 }
00620 *cp = 0;
00621
00622 return cnt;
00623 }
00624