Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F3071325
brotli.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
brotli.c
View Options
#include
<stdlib.h>
#include
<string.h>
#include
<brotli/encode.h>
#include
<brotli/decode.h>
#include
"ant.h"
#include
"errors.h"
#include
"internal.h"
#include
"modules/buffer.h"
#include
"streams/brotli.h"
#include
"streams/transform.h"
#define BROTLI_CHUNK_SIZE (32 * 1024)
struct
brotli_stream_state
{
bool
decompress
;
union
{
BrotliEncoderState
*
enc
;
BrotliDecoderState
*
dec
;
}
u
;
};
static
int
brotli_emit_chunk
(
brotli_stream_chunk_cb
cb
,
void
*
ctx
,
const
uint8_t
*
data
,
size_t
len
)
{
if
(
!
cb
||
len
==
0
)
return
0
;
return
cb
(
ctx
,
data
,
len
);
}
static
ant_value_t
brotli_enqueue_buffer
(
ant_t
*
js
,
ant_value_t
ctrl_obj
,
const
uint8_t
*
data
,
size_t
len
)
{
ArrayBufferData
*
ab
=
create_array_buffer_data
(
len
);
if
(
!
ab
)
return
js_mkerr
(
js
,
"out of memory"
);
memcpy
(
ab
->
data
,
data
,
len
);
ant_value_t
arr
=
create_typed_array
(
js
,
TYPED_ARRAY_UINT8
,
ab
,
0
,
len
,
"Uint8Array"
);
if
(
!
ts_is_controller
(
ctrl_obj
))
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"Invalid TransformStreamDefaultController"
);
return
ts_ctrl_enqueue
(
js
,
ctrl_obj
,
arr
);
}
static
int
brotli_encoder_step
(
brotli_stream_state_t
*
st
,
const
uint8_t
*
input
,
size_t
input_len
,
BrotliEncoderOperation
op
,
brotli_stream_chunk_cb
cb
,
void
*
ctx
)
{
size_t
avail_in
=
input_len
;
const
uint8_t
*
next_in
=
input
;
for
(;;)
{
uint8_t
out_buf
[
BROTLI_CHUNK_SIZE
];
uint8_t
*
next_out
=
out_buf
;
size_t
avail_out
=
sizeof
(
out_buf
);
if
(
!
BrotliEncoderCompressStream
(
st
->
u
.
enc
,
op
,
&
avail_in
,
&
next_in
,
&
avail_out
,
&
next_out
,
NULL
))
{
return
-1
;
}
size_t
have
=
sizeof
(
out_buf
)
-
avail_out
;
if
(
brotli_emit_chunk
(
cb
,
ctx
,
out_buf
,
have
)
!=
0
)
return
-1
;
if
(
op
==
BROTLI_OPERATION_FINISH
)
{
if
(
BrotliEncoderIsFinished
(
st
->
u
.
enc
)
&&
!
BrotliEncoderHasMoreOutput
(
st
->
u
.
enc
))
break
;
}
else
if
(
avail_in
==
0
&&
!
BrotliEncoderHasMoreOutput
(
st
->
u
.
enc
))
break
;
}
return
0
;
}
static
int
brotli_decoder_step
(
brotli_stream_state_t
*
st
,
const
uint8_t
*
input
,
size_t
input_len
,
brotli_stream_chunk_cb
cb
,
void
*
ctx
)
{
size_t
avail_in
=
input_len
;
const
uint8_t
*
next_in
=
input
;
for
(;;)
{
uint8_t
out_buf
[
BROTLI_CHUNK_SIZE
];
uint8_t
*
next_out
=
out_buf
;
size_t
avail_out
=
sizeof
(
out_buf
);
BrotliDecoderResult
ret
=
BrotliDecoderDecompressStream
(
st
->
u
.
dec
,
&
avail_in
,
&
next_in
,
&
avail_out
,
&
next_out
,
NULL
);
size_t
have
=
sizeof
(
out_buf
)
-
avail_out
;
if
(
brotli_emit_chunk
(
cb
,
ctx
,
out_buf
,
have
)
!=
0
)
return
-1
;
if
(
ret
==
BROTLI_DECODER_RESULT_ERROR
)
return
-1
;
if
(
ret
==
BROTLI_DECODER_RESULT_SUCCESS
)
break
;
if
(
ret
==
BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT
||
BrotliDecoderHasMoreOutput
(
st
->
u
.
dec
))
continue
;
if
(
ret
==
BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT
)
break
;
}
return
0
;
}
brotli_stream_state_t
*
brotli_stream_state_new
(
bool
decompress
)
{
brotli_stream_state_t
*
st
=
calloc
(
1
,
sizeof
(
*
st
));
if
(
!
st
)
return
NULL
;
st
->
decompress
=
decompress
;
if
(
decompress
)
{
st
->
u
.
dec
=
BrotliDecoderCreateInstance
(
NULL
,
NULL
,
NULL
);
if
(
!
st
->
u
.
dec
)
{
free
(
st
);
return
NULL
;
}}
else
{
st
->
u
.
enc
=
BrotliEncoderCreateInstance
(
NULL
,
NULL
,
NULL
);
if
(
!
st
->
u
.
enc
)
{
free
(
st
);
return
NULL
;
}}
return
st
;
}
void
brotli_stream_state_destroy
(
brotli_stream_state_t
*
st
)
{
if
(
!
st
)
return
;
if
(
st
->
decompress
)
BrotliDecoderDestroyInstance
(
st
->
u
.
dec
);
else
BrotliEncoderDestroyInstance
(
st
->
u
.
enc
);
free
(
st
);
}
int
brotli_stream_process
(
brotli_stream_state_t
*
st
,
const
uint8_t
*
input
,
size_t
input_len
,
brotli_stream_chunk_cb
cb
,
void
*
ctx
)
{
if
(
!
st
)
return
-1
;
if
(
st
->
decompress
)
return
brotli_decoder_step
(
st
,
input
,
input_len
,
cb
,
ctx
);
return
brotli_encoder_step
(
st
,
input
,
input_len
,
BROTLI_OPERATION_PROCESS
,
cb
,
ctx
);
}
int
brotli_stream_finish
(
brotli_stream_state_t
*
st
,
brotli_stream_chunk_cb
cb
,
void
*
ctx
)
{
if
(
!
st
)
return
-1
;
if
(
st
->
decompress
)
{
if
(
brotli_decoder_step
(
st
,
NULL
,
0
,
cb
,
ctx
)
!=
0
)
return
-1
;
return
BrotliDecoderIsFinished
(
st
->
u
.
dec
)
?
0
:
-1
;
}
return
brotli_encoder_step
(
st
,
NULL
,
0
,
BROTLI_OPERATION_FINISH
,
cb
,
ctx
);
}
bool
brotli_stream_is_finished
(
brotli_stream_state_t
*
st
)
{
if
(
!
st
)
return
false
;
if
(
st
->
decompress
)
return
BrotliDecoderIsFinished
(
st
->
u
.
dec
);
return
BrotliEncoderIsFinished
(
st
->
u
.
enc
);
}
typedef
struct
{
ant_t
*
js
;
ant_value_t
ctrl_obj
;
ant_value_t
error
;
}
brotli_js_emit_ctx_t
;
static
int
brotli_enqueue_chunk_cb
(
void
*
ctx
,
const
uint8_t
*
chunk
,
size_t
len
)
{
brotli_js_emit_ctx_t
*
emit
=
(
brotli_js_emit_ctx_t
*
)
ctx
;
ant_value_t
result
=
brotli_enqueue_buffer
(
emit
->
js
,
emit
->
ctrl_obj
,
chunk
,
len
);
if
(
is_err
(
result
))
{
emit
->
error
=
result
;
return
-1
;
}
return
0
;
}
ant_value_t
brotli_stream_transform
(
ant_t
*
js
,
brotli_stream_state_t
*
st
,
ant_value_t
ctrl_obj
,
const
uint8_t
*
input
,
size_t
input_len
)
{
brotli_js_emit_ctx_t
emit
=
{
.
js
=
js
,
.
ctrl_obj
=
ctrl_obj
,
.
error
=
js_mkundef
()
};
if
(
brotli_stream_process
(
st
,
input
,
input_len
,
brotli_enqueue_chunk_cb
,
&
emit
)
!=
0
)
{
if
(
is_err
(
emit
.
error
))
return
emit
.
error
;
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
st
&&
st
->
decompress
?
"Decompression failed"
:
"Compression failed"
);
}
return
js_mkundef
();
}
ant_value_t
brotli_stream_flush
(
ant_t
*
js
,
brotli_stream_state_t
*
st
,
ant_value_t
ctrl_obj
)
{
brotli_js_emit_ctx_t
emit
=
{
.
js
=
js
,
.
ctrl_obj
=
ctrl_obj
,
.
error
=
js_mkundef
()
};
if
(
brotli_stream_finish
(
st
,
brotli_enqueue_chunk_cb
,
&
emit
)
!=
0
)
{
if
(
is_err
(
emit
.
error
))
return
emit
.
error
;
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
st
&&
st
->
decompress
?
"Decompression failed"
:
"Compression failed"
);
}
return
js_mkundef
();
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Sat, Apr 4, 12:36 AM (2 d)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
520838
Default Alt Text
brotli.c (5 KB)
Attached To
Mode
rANT Ant
Attached
Detach File
Event Timeline
Log In to Comment