HTTP_ARG_VAL(data, 0)
HTTP_END_ARGS;
-HTTP_EMPTY_ARGS(finish, 0);
+HTTP_BEGIN_ARGS(flush, 0, 0)
+ HTTP_ARG_VAL(data, 0)
+HTTP_END_ARGS;
+
+HTTP_BEGIN_ARGS(finish, 0, 0)
+ HTTP_ARG_VAL(data, 0)
+HTTP_END_ARGS;
#define http_deflatestream_object_declare_default_properties() _http_deflatestream_object_declare_default_properties(TSRMLS_C)
static inline void _http_deflatestream_object_declare_default_properties(TSRMLS_D);
zend_function_entry http_deflatestream_object_fe[] = {
HTTP_DEFLATE_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
HTTP_DEFLATE_ME(update, ZEND_ACC_PUBLIC)
+ HTTP_DEFLATE_ME(flush, ZEND_ACC_PUBLIC)
HTTP_DEFLATE_ME(finish, ZEND_ACC_PUBLIC)
EMPTY_FUNCTION_ENTRY
RETURN_FALSE;
}
- if (!obj->stream) {
- if (!(obj->stream = http_encoding_deflate_stream_init(NULL, 0))) {
- RETURN_FALSE;
- }
+ if (!obj->stream && !(obj->stream = http_encoding_deflate_stream_init(NULL, 0))) {
+ RETURN_FALSE;
}
if (SUCCESS == http_encoding_deflate_stream_update(obj->stream, data, data_len, &encoded, &encoded_len)) {
}
/* }}} */
-/* {{{ proto string HttpDeflateStream::finish()
+/* {{{ proto string HttpDeflateStream::flush([string data])
+ *
+ * Flushes the deflate stream.
+ *
+ * Returns some deflated data as string on success or FALSE on failure.
+ */
+PHP_METHOD(HttpDeflateStream, flush)
+{
+ int data_len = 0;
+ size_t updated_len = 0, encoded_len = 0;
+ char *updated = NULL, *encoded = NULL, *data = NULL;
+ getObject(http_deflatestream_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) {
+ RETURN_FALSE;
+ }
+
+ if (!obj->stream && !(obj->stream = http_encoding_deflate_stream_init(NULL, 0))) {
+ RETURN_FALSE;
+ }
+
+ if (data_len) {
+ if (SUCCESS != http_encoding_deflate_stream_update(obj->stream, data, data_len, &updated, &updated_len)) {
+ RETURN_FALSE;
+ }
+ }
+
+ if (SUCCESS == http_encoding_deflate_stream_flush(obj->stream, &encoded, &encoded_len)) {
+ if (updated_len) {
+ updated = erealloc(updated, updated_len + encoded_len + 1);
+ updated[updated_len + encoded_len] = '\0';
+ memcpy(updated + updated_len, encoded, encoded_len);
+ STR_FREE(encoded);
+ updated_len += encoded_len;
+ RETURN_STRINGL(updated, updated_len, 0);
+ } else {
+ RETVAL_STRINGL(encoded, encoded_len, 0);
+ }
+ } else {
+ RETVAL_FALSE;
+ }
+ STR_FREE(updated);
+}
+/* }}} */
+
+/* {{{ proto string HttpDeflateStream::finish([string data])
*
* Finalizes the deflate stream. The deflate stream can be reused after finalizing.
*
*/
PHP_METHOD(HttpDeflateStream, finish)
{
- size_t encoded_len = 0;
- char *encoded = NULL;
+ int data_len = 0;
+ size_t updated_len = 0, encoded_len = 0;
+ char *updated = NULL, *encoded = NULL, *data = NULL;
getObject(http_deflatestream_object, obj);
- NO_ARGS;
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) {
+ RETURN_FALSE;
+ }
- if (!obj->stream) {
+ if (!obj->stream && !(obj->stream = http_encoding_deflate_stream_init(NULL, 0))) {
RETURN_FALSE;
}
+ if (data_len) {
+ if (SUCCESS != http_encoding_deflate_stream_update(obj->stream, data, data_len, &updated, &updated_len)) {
+ RETURN_FALSE;
+ }
+ }
+
if (SUCCESS == http_encoding_deflate_stream_finish(obj->stream, &encoded, &encoded_len)) {
- RETVAL_STRINGL(encoded, encoded_len, 0);
+ if (updated_len) {
+ updated = erealloc(updated, updated_len + encoded_len + 1);
+ updated[updated_len + encoded_len] = '\0';
+ memcpy(updated + updated_len, encoded, encoded_len);
+ STR_FREE(encoded);
+ updated_len += encoded_len;
+ RETVAL_STRINGL(updated, updated_len, 0);
+ } else {
+ STR_FREE(updated);
+ RETVAL_STRINGL(encoded, encoded_len, 0);
+ }
} else {
+ STR_FREE(updated);
RETVAL_FALSE;
}
case Z_OK:
case Z_STREAM_END:
/* cut processed chunk off the buffer */
- phpstr_cut(PHPSTR(s->stream.opaque), 0, data_len - s->stream.avail_in);
+ phpstr_cut(PHPSTR(s->stream.opaque), 0, PHPSTR_LEN(s->stream.opaque) - s->stream.avail_in);
/* size buffer down to actual size */
*encoded_len -= s->stream.avail_out;
case Z_OK:
case Z_STREAM_END:
/* cut off */
- phpstr_cut(PHPSTR(s->stream.opaque), 0, data_len - s->stream.avail_in);
+ phpstr_cut(PHPSTR(s->stream.opaque), 0, PHPSTR_LEN(s->stream.opaque) - s->stream.avail_in);
/* size down */
*decoded_len -= s->stream.avail_out;
PHP_HTTP_API STATUS _http_encoding_inflate_stream_flush(http_encoding_stream *s, char **decoded, size_t *decoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
{
- int status;
-
- *decoded_len = 0x800;
- *decoded = emalloc_rel(*decoded_len);
-
- s->stream.avail_in = 0;
- s->stream.next_in = NULL;
- s->stream.avail_out = *decoded_len;
- s->stream.next_out = (Bytef *) *decoded;
-
- switch (status = inflate(&s->stream, Z_SYNC_FLUSH))
- {
- case Z_OK:
- case Z_STREAM_END:
- *decoded_len = 0x800 - s->stream.avail_out;
- *decoded = erealloc_rel(*decoded, *decoded_len + 1);
- (*decoded)[*decoded_len] = '\0';
- return SUCCESS;
- break;
- }
-
- STR_SET(*decoded, NULL);
- *decoded_len = 0;
- http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to flush inflate stream: %s", zError(status));
- return FAILURE;
+ /* noop */
+ *decoded = estrndup("", *decoded_len = 0);
+ return SUCCESS;
}
PHP_HTTP_API STATUS _http_encoding_deflate_stream_finish(http_encoding_stream *s, char **encoded, size_t *encoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
HTTP_ARG_VAL(data, 0)
HTTP_END_ARGS;
-HTTP_EMPTY_ARGS(finish, 0);
+HTTP_BEGIN_ARGS(flush, 0, 0)
+ HTTP_ARG_VAL(data, 0)
+HTTP_END_ARGS;
+
+HTTP_BEGIN_ARGS(finish, 0, 0)
+ HTTP_ARG_VAL(data, 0)
+HTTP_END_ARGS;
zend_class_entry *http_inflatestream_object_ce;
zend_function_entry http_inflatestream_object_fe[] = {
HTTP_INFLATE_ME(update, ZEND_ACC_PUBLIC)
+ HTTP_INFLATE_ME(flush, ZEND_ACC_PUBLIC)
HTTP_INFLATE_ME(finish, ZEND_ACC_PUBLIC)
EMPTY_FUNCTION_ENTRY
RETURN_STRING("", 1);
}
- if (!obj->stream) {
- if (!(obj->stream = http_encoding_inflate_stream_init(NULL, 0))) {
- RETURN_FALSE;
- }
+ if (!obj->stream && !(obj->stream = http_encoding_inflate_stream_init(NULL, 0))) {
+ RETURN_FALSE;
}
+
if (SUCCESS == http_encoding_inflate_stream_update(obj->stream, data, data_len, &decoded, &decoded_len)) {
RETURN_STRINGL(decoded, decoded_len, 0);
} else {
}
/* }}} */
-/* {{{ proto string HttpInflateStream::finish()
+/* {{{ proto string HttpInflateStream::flush([string data])
+ *
+ * Flush the inflate stream.
+ *
+ * Returns some inflated data as string on success or FALSE on failure.
+ */
+PHP_METHOD(HttpInflateStream, flush)
+{
+ int data_len = 0;
+ size_t decoded_len = 0;
+ char *decoded = NULL, *data = NULL;
+ getObject(http_inflatestream_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len));
+
+ if (!obj->stream && !(obj->stream = http_encoding_inflate_stream_init(NULL, 0))) {
+ RETURN_FALSE;
+ }
+
+ /* flushing the inflate stream is a no-op */
+ if (!data_len) {
+ RETURN_STRINGL("", 0, 1);
+ } else if (SUCCESS == http_encoding_inflate_stream_update(obj->stream, data, data_len, &decoded, &decoded_len)) {
+ RETURN_STRINGL(decoded, decoded_len, 0);
+ } else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto string HttpInflateStream::finish([string data])
*
* Finalizes the inflate stream. The inflate stream can be reused after finalizing.
*
*/
PHP_METHOD(HttpInflateStream, finish)
{
- size_t decoded_len = 0;
- char *decoded = NULL;
+ int data_len = 0;
+ size_t updated_len = 0, decoded_len = 0;
+ char *updated = NULL, *decoded = NULL, *data = NULL;
getObject(http_inflatestream_object, obj);
- NO_ARGS;
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) {
+ RETURN_FALSE;
+ }
- if (!obj->stream) {
+ if (!obj->stream && !(obj->stream = http_encoding_inflate_stream_init(NULL, 0))) {
RETURN_FALSE;
}
+ if (data_len) {
+ if (SUCCESS != http_encoding_inflate_stream_update(obj->stream, data, data_len, &updated, &updated_len)) {
+ RETURN_FALSE;
+ }
+ }
+
if (SUCCESS == http_encoding_inflate_stream_finish(obj->stream, &decoded, &decoded_len)) {
- RETVAL_STRINGL(decoded, decoded_len, 0);
+ if (updated_len) {
+ updated = erealloc(updated, updated_len + decoded_len + 1);
+ updated[updated_len + decoded_len] = '\0';
+ memcpy(updated + updated_len, decoded, decoded_len);
+ updated_len += decoded_len;
+ RETVAL_STRINGL(updated, updated_len, 0);
+ STR_FREE(decoded);
+ } else {
+ RETVAL_STRINGL(decoded, decoded_len, 0);
+ STR_FREE(updated);
+ }
} else {
RETVAL_FALSE;
}
PHP_METHOD(HttpDeflateStream, __construct);
PHP_METHOD(HttpDeflateStream, update);
+PHP_METHOD(HttpDeflateStream, flush);
PHP_METHOD(HttpDeflateStream, finish);
#endif
extern void _http_inflatestream_object_free(zend_object *object TSRMLS_DC);
PHP_METHOD(HttpInflateStream, update);
+PHP_METHOD(HttpInflateStream, flush);
PHP_METHOD(HttpInflateStream, finish);
#endif
echo "-TEST\n";
$d = new HttpDeflateStream;
$i = new HttpInflateStream;
-echo $i->update($d->update("Hi "));
-echo $i->update($d->update("there!\n"));
-echo $i->update($d->finish());
-echo $i->finish();
+echo $i->flush($d->flush("Hi "));
+echo $i->finish($d->finish("there!\n"));
+echo $i->finish($d->finish("Yo...\n"));
echo "Done\n";
?>
--EXPECTF--
%sTEST
Hi there!
+Yo...
Done