How used Brotli Decoder in Objective-C #450

Closed
opened 2026-01-29 20:44:05 +00:00 by claunia · 1 comment
Owner

Originally created by @iHTCboy on GitHub (Feb 23, 2023).

ChatGPT:

- (NSData *)decodeBrotliData:(NSData *)compressedData {
    size_t decompressedLength = BrotliDecoderDecompressedSize([compressedData length], [compressedData bytes]);
    if (decompressedLength == BROTLI_DECODER_RESULT_ERROR) {
        NSLog(@"Failed to decompress Brotli encoding data");
        return nil;
    }

    NSMutableData *decompressedData = [NSMutableData dataWithLength:decompressedLength];
    size_t outSize = [decompressedData length];
    const uint8_t *compressedBytes = [compressedData bytes];
    uint8_t *outBytes = [decompressedData mutableBytes];

    if (BrotliDecoderDecompress(0, compressedBytes, [compressedData length], &outSize, outBytes) != BROTLI_DECODER_RESULT_SUCCESS) {
        NSLog(@"Failed to decompress Brotli encoding data");
        return nil;
    }

    return decompressedData;
}

BrotliDecoderDecompressedSize Can't find

Originally created by @iHTCboy on GitHub (Feb 23, 2023). ChatGPT: ``` - (NSData *)decodeBrotliData:(NSData *)compressedData { size_t decompressedLength = BrotliDecoderDecompressedSize([compressedData length], [compressedData bytes]); if (decompressedLength == BROTLI_DECODER_RESULT_ERROR) { NSLog(@"Failed to decompress Brotli encoding data"); return nil; } NSMutableData *decompressedData = [NSMutableData dataWithLength:decompressedLength]; size_t outSize = [decompressedData length]; const uint8_t *compressedBytes = [compressedData bytes]; uint8_t *outBytes = [decompressedData mutableBytes]; if (BrotliDecoderDecompress(0, compressedBytes, [compressedData length], &outSize, outBytes) != BROTLI_DECODER_RESULT_SUCCESS) { NSLog(@"Failed to decompress Brotli encoding data"); return nil; } return decompressedData; } ``` `BrotliDecoderDecompressedSize` Can't find
Author
Owner

@iHTCboy commented on GitHub (Feb 24, 2023):

Brotli/NSData+Brotli.m at master · karlvr/Brotli

- (NSData *)brotliDecompressedAllowPartialInput:(BOOL)allowPartialInput {
    size_t available_in = self.length;
    const uint8_t *next_in = self.bytes;

    const int decompressionBufferSize = 8192;
    uint8_t* decompressedBuffer = (uint8_t*) malloc(decompressionBufferSize * sizeof(uint8_t));
    BOOL usedDecompressedBufferInResult = NO;

    NSMutableData *resultData = nil;

    BrotliDecoderState *s = BrotliDecoderCreateInstance(NULL, NULL, NULL);
    BrotliDecoderResult result = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;

    size_t total_out = 0;

    /* Loop while the decoder wants more space to output. */
    while (result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
        size_t available_out = decompressionBufferSize;
        uint8_t *next_out = decompressedBuffer;

        result = BrotliDecoderDecompressStream(s, &available_in, &next_in, &available_out, &next_out, &total_out);

        const size_t written = decompressionBufferSize - available_out;

        if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT || result == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) {
            /* Partial result, so accumulate in `resultData` */
            if (resultData == nil) {
                resultData = [NSMutableData dataWithBytes:decompressedBuffer length:written];
            } else {
                [resultData appendBytes:decompressedBuffer length:written];
            }
        } else if (result == BROTLI_DECODER_RESULT_SUCCESS) {
            /* Complete result, so either append to existing buffer or create the final result buffer */
            if (resultData) {
                [resultData appendBytes:decompressedBuffer length:written];
            } else {
                resultData = (NSMutableData*) [NSData dataWithBytesNoCopy:decompressedBuffer length:total_out freeWhenDone:YES];
                usedDecompressedBufferInResult = YES;
            }
        }
    }

    BrotliDecoderDestroyInstance(s);

    if (!usedDecompressedBufferInResult) {
        free(decompressedBuffer);
    }

    if (result == BROTLI_DECODER_RESULT_SUCCESS) {
        return resultData;
    } else if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT && allowPartialInput) {
        return resultData;
    } else {
        return nil;
    }
}
@iHTCboy commented on GitHub (Feb 24, 2023): [Brotli/NSData+Brotli.m at master · karlvr/Brotli](https://github.com/karlvr/Brotli/blob/master/Brotli/Classes/NSData%2BBrotli.m) ```ojbC - (NSData *)brotliDecompressedAllowPartialInput:(BOOL)allowPartialInput { size_t available_in = self.length; const uint8_t *next_in = self.bytes; const int decompressionBufferSize = 8192; uint8_t* decompressedBuffer = (uint8_t*) malloc(decompressionBufferSize * sizeof(uint8_t)); BOOL usedDecompressedBufferInResult = NO; NSMutableData *resultData = nil; BrotliDecoderState *s = BrotliDecoderCreateInstance(NULL, NULL, NULL); BrotliDecoderResult result = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT; size_t total_out = 0; /* Loop while the decoder wants more space to output. */ while (result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) { size_t available_out = decompressionBufferSize; uint8_t *next_out = decompressedBuffer; result = BrotliDecoderDecompressStream(s, &available_in, &next_in, &available_out, &next_out, &total_out); const size_t written = decompressionBufferSize - available_out; if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT || result == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) { /* Partial result, so accumulate in `resultData` */ if (resultData == nil) { resultData = [NSMutableData dataWithBytes:decompressedBuffer length:written]; } else { [resultData appendBytes:decompressedBuffer length:written]; } } else if (result == BROTLI_DECODER_RESULT_SUCCESS) { /* Complete result, so either append to existing buffer or create the final result buffer */ if (resultData) { [resultData appendBytes:decompressedBuffer length:written]; } else { resultData = (NSMutableData*) [NSData dataWithBytesNoCopy:decompressedBuffer length:total_out freeWhenDone:YES]; usedDecompressedBufferInResult = YES; } } } BrotliDecoderDestroyInstance(s); if (!usedDecompressedBufferInResult) { free(decompressedBuffer); } if (result == BROTLI_DECODER_RESULT_SUCCESS) { return resultData; } else if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT && allowPartialInput) { return resultData; } else { return nil; } } ```
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/brotli#450