tsf_bool_t tsf_adaptive_reader_read()

in benchmarks/JetStream2/wasm/TSF/tsf_adaptive_reader.c [335:506]


tsf_bool_t tsf_adaptive_reader_read(void *_reader,
				    void *_data,
				    uint32_t len) {
    tsf_adpt_rdr_t *reader=_reader;
    uint8_t *data=_data;
    
    if (len==0) {
	return tsf_true;
    }
    
    /* this just constitutes lazy initialization upon read */
    if (reader->mode==TSF_ZIP_UNKNOWN) {
	if (!select_mode(reader,NULL,0,tsf_false)) {
	    return tsf_false;
	}
    }

    switch (reader->mode) {
    case TSF_ZIP_NONE: {
	/* ok - this code is complicated.  it is complicated because it
	   needs to deal with the possibility of a format change - if the
	   magic code for one of the zip formats comes in, this thing's job
	   is to recognize it and switch from no-zip buffering to unzipping.
	   we use the hint_switch() function calls as a hint of when to
	   look for the format changes. */
	if (reader->expect_switch && reader->puti>reader->geti) {
	    reader->expect_switch=tsf_false;
	    if (reader->buf[reader->geti]==TSF_SP_C_SWITCH_FORMAT) {
		if (!tear_down_and_select_mode(reader)) {
		    return tsf_false;
		}
		return tsf_adaptive_reader_read(reader,data,len);
	    }
	}
	uint32_t toread=tsf_min(reader->puti-reader->geti,len);
	memcpy(data,reader->buf+reader->geti,toread);
	reader->geti+=toread;
	data+=toread;
	len-=toread;
	if (len>reader->buf_size) {
	    tsf_assert(reader->geti==reader->puti);
	    if (reader->expect_switch) {
		int32_t res=reader->reader(reader->reader_arg,
					   data,len);
		if (res<0) {
		    return tsf_false;
		}
		tsf_assert(res>0);
		if (data[0]==TSF_SP_C_SWITCH_FORMAT) {
		    tear_down_mode(reader,NULL,NULL);
		    if (!select_mode(reader,data,res,tsf_false)) {
			return tsf_false;
		    }
		    return tsf_adaptive_reader_read(reader,data,len);
		} else {
		    data+=res;
		    len-=res;
		}
	    }
	    if (!tsf_full_read_of_partial(reader->reader,
					  reader->reader_arg,
					  data,
					  len)) {
		if (tsf_get_error_code()==TSF_E_UNEXPECTED_EOF
		    && data!=_data) {
		    tsf_set_error(TSF_E_ERRONEOUS_EOF,
				  "End-of-file after part of a full buffered "
				  "read; original error: %s",tsf_get_error());
		}
		return tsf_false;
	    }
	} else if (len>0) {
	    reader->puti=0;
	    reader->geti=0;
	    for (;;) {
		int32_t res;
		uint32_t tocopy;
		res=reader->reader(reader->reader_arg,
				   reader->buf,
				   reader->buf_size);
		if (res<0) {
		    if (tsf_get_error_code()==TSF_E_UNEXPECTED_EOF
			&& data!=_data) {
			tsf_set_error(TSF_E_ERRONEOUS_EOF,
				      "End-of-file after part of a full buffered "
				      "read; original error: %s",tsf_get_error());
		    }
		    return tsf_false;
		}
		tsf_assert(res>0);
		if (reader->expect_switch) {
		    reader->expect_switch=tsf_false;
		    if (reader->buf[0]==TSF_SP_C_SWITCH_FORMAT) {
			reader->puti=res;
			if (!tear_down_and_select_mode(reader)) {
			    return tsf_false;
			}
			return tsf_adaptive_reader_read(reader,data,len);
		    }
		}
		tocopy=tsf_min(res,len);
		memcpy(data,reader->buf,tocopy);
		data+=tocopy;
		len-=tocopy;
		if (len==0) {
		    reader->puti=res;
		    reader->geti=tocopy;
		    break;
		}
	    }
	}
	break;
    }
    case TSF_ZIP_ZLIB:
    case TSF_ZIP_BZIP2: {
	reader->abstract.next_out=data;
	reader->abstract.avail_out=len;
	
	for (;;) {
	    int res;

	    /* is there ever a case where we would want to call inflate even though
	       the input buffer is empty? */
	    if (reader->abstract.avail_in!=0) {
		res=tsf_zip_abstract_inflate(reader->mode,
					     reader->stream,
					     &(reader->abstract),
					     TSF_ZIP_ACT_RUN);
		
		if (res==TSF_ZIP_RES_ERROR) {
		    return tsf_false;
		} else if (res==TSF_ZIP_RES_END) {
		    if (reader->abstract.avail_out!=0) {
			tsf_set_error(TSF_E_PARSE_ERROR,
				      "A read request straddles a format change");
		    }
		    tear_to_none(reader);
		}
		
		if (reader->abstract.avail_out==0) {
		    break;
		}
		
		tsf_assert(reader->abstract.avail_in==0);
	    }
	    
	    res=reader->reader(reader->reader_arg,
			       reader->buf,
			       reader->buf_size);
	    
	    if (res==-1) {
		if (tsf_get_error_code()==TSF_E_UNEXPECTED_EOF) {
		    tsf_set_error(TSF_E_ERRONEOUS_EOF,
				  "Got an EOF from the reader before the "
				  "decompressor had reached end of stream");
		}
		return tsf_false;
	    }
	    
	    reader->abstract.next_in=reader->buf;
	    reader->abstract.avail_in=res;
	}
	break;
    }
    default:
	tsf_set_error(TSF_E_INTERNAL,
		      "Invalid reader mode in tsf_adaptive_reader_read()");
	return tsf_false;
    }
    
    return tsf_true;
}