Malcolm McLean said:
בת×ריך ×™×•× ×¨×‘×™×¢×™, 29 ב×וגוסט 2012 03:27:46 UTC+1, מ×ת Bill Cunningham:
/*
find a tag / string in a stream.
Params: fp - pointer to open file
tag - return for tag.
Returns: 0 = no tag in file, 1 = seek to tag , -1 error or some sort
Notes: Not tag structure aware, so some tags may be be spurious.
Notes: untested
*/
int seektag(FILE *fp, char *tag)
A note the anyone learning C: Malcolm objects to both "const" and
"size_t" so this function won't work with const char * arguments
(without a cast) and it contains a lot of needless signed/unsigned int
conversions. I'd add const above and declare N below as size_t.
(Malcolm: I'm not trying to convert you, but I think your opinion is
singular enough to merit being pointed out.)
{
int ch;
char *buff;
int N;
long pos;
N = strlen(tag);
buff = malloc(N);
if(!buff)
return -1;
while( (ch = fgetc(fp)) != EOF)
{
if(ch == buff[0])
Typo: you mean tag[0] of course.
{
ungetc(ch, fp);
pos = ftell(fp);
if( fread(buff, 1, N, fp) != N)
{
free(buff);
return -1;
}
if(!strncmp(buff, tag, N))
{
fseek(fp, pos, SEEK_SET);
free(buff);
return 1;
}
}
}
/* weve got to the end without finding the tag */
free(buff);
if(ferror(fp))
return -1;
return 0;
}
I think this is working too hard. I'd match as we go, mainly because it
avoid using a buffer. I think the result is clearer:
int seektag(FILE *fp, const char *tag)
{
int ch;
size_t match = 0, tlen = strlen(tag);
long pos;
while (match < tlen && (ch = fgetc(fp)) != EOF)
if (ch == tag[match]) {
if (match == 0) {
ungetc(ch, fp);
pos = ftell(fp);
fgetc(fp);
}
match += 1;
}
else match = 0;
if (match == tlen) {
fseek(fp, pos, SEEK_SET);
return 1;
}
if (ferror(fp))
return -1;
return 0;
}
I'd be inclined protect against empty tag strings, but your code did not
so I copied that decision.
It's even simpler if you are prepared to rely on SEEK_CUR (i.e. a binary
stream):
int seektag(FILE *fp, const char *tag)
{
int ch;
size_t match = 0, tlen = strlen(tag);
while (match < tlen && (ch = fgetc(fp)) != EOF)
if (ch == tag[match])
match += 1;
else match = 0;
if (match == tlen) {
fseek(fp, -(long)tlen, SEEK_CUR);
return 1;
}
if (ferror(fp))
return -1;
return 0;
}