← Back to Reports Index

CELLO Evaluation Report: buffer

Generated: 2026-02-16T12:12:34.564677

Original C Code (1997 bytes)

/* Dynamic buffer implementation - common pattern in C infrastructure */

#include <stdlib.h>
#include <string.h>

typedef struct {
    char* data;
    size_t size;      // Current size
    size_t capacity;  // Allocated capacity
} Buffer;

/**
 * Initialize a new buffer with initial capacity
 */
Buffer* buffer_new(size_t initial_capacity) {
    Buffer* buf = (Buffer*)malloc(sizeof(Buffer));
    if (!buf) return NULL;
    
    buf->data = (char*)malloc(initial_capacity);
    if (!buf->data) {
        free(buf);
        return NULL;
    }
    
    buf->size = 0;
    buf->capacity = initial_capacity;
    buf->data[0] = '\0';
    
    return buf;
}

/**
 * Grow buffer capacity (doubles current capacity)
 */
static int buffer_grow(Buffer* buf) {
    if (!buf) return -1;
    
    size_t new_capacity = buf->capacity * 2;
    if (new_capacity < 16) new_capacity = 16;
    
    char* new_data = (char*)realloc(buf->data, new_capacity);
    if (!new_data) return -1;
    
    buf->data = new_data;
    buf->capacity = new_capacity;
    return 0;
}

/**
 * Append data to buffer
 */
int buffer_append(Buffer* buf, const char* data, size_t len) {
    if (!buf || !data) return -1;
    
    while (buf->size + len + 1 > buf->capacity) {
        if (buffer_grow(buf) != 0) return -1;
    }
    
    memcpy(buf->data + buf->size, data, len);
    buf->size += len;
    buf->data[buf->size] = '\0';
    
    return 0;
}

/**
 * Append a string to buffer
 */
int buffer_append_str(Buffer* buf, const char* str) {
    if (!str) return -1;
    return buffer_append(buf, str, strlen(str));
}

/**
 * Clear buffer contents
 */
void buffer_clear(Buffer* buf) {
    if (!buf) return;
    buf->size = 0;
    if (buf->data) buf->data[0] = '\0';
}

/**
 * Free buffer and its data
 */
void buffer_free(Buffer* buf) {
    if (!buf) return;
    free(buf->data);
    free(buf);
}

/**
 * Get current buffer contents as C string
 */
const char* buffer_cstr(const Buffer* buf) {
    return buf ? buf->data : NULL;
}

CLAUDE Transpilation

Overall Score: 77/100
Dimension Score Max Details
Compilation 25 25 ✓ Compiles successfully
Safety 18 20 ✓ No unsafe blocks | ✓ Uses Result for error handling | ✓ Uses Option for nullable values
Quality 14 20 ✓ Snake_case naming | ✓ Well documented (10 doc comments) | ✓ Proper type definitions | ✓ Implementation blocks
Correctness 7 15 ✓ Edge case checks | ✓ Pattern matching
Maintainability 3 10 ✓ Clear public API (10 items)
Performance 10 10 ✓ Minimal cloning | ✓ Reference usage

✅ Compilation: PASSED

Generated Rust Code (1976 bytes)

/// Dynamic buffer implementation for managing growable byte arrays
pub struct Buffer {
    data: Vec<u8>,
}

impl Buffer {
    /// Initialize a new buffer with initial capacity
    pub fn new(initial_capacity: usize) -> Self {
        Buffer {
            data: Vec::with_capacity(initial_capacity),
        }
    }

    /// Append data to buffer
    pub fn append(&mut self, data: &[u8]) -> Result<(), BufferError> {
        self.data.extend_from_slice(data);
        Ok(())
    }

    /// Append a string to buffer
    pub fn append_str(&mut self, s: &str) -> Result<(), BufferError> {
        self.append(s.as_bytes())
    }

    /// Clear buffer contents
    pub fn clear(&mut self) {
        self.data.clear();
    }

    /// Get current buffer contents as C string (null-terminated)
    pub fn as_cstr(&self) -> Option<&std::ffi::CStr> {
        if self.data.is_empty() || self.data.last() != Some(&0) {
            return None;
        }
        std::ffi::CStr::from_bytes_with_nul(&self.data).ok()
    }

    /// Get current buffer contents as byte slice
    pub fn as_bytes(&self) -> &[u8] {
        &self.data
    }

    /// Get current buffer contents as string slice if valid UTF-8
    pub fn as_str(&self) -> Result<&str, std::str::Utf8Error> {
        std::str::from_utf8(&self.data)
    }

    /// Get current size of buffer
    pub fn size(&self) -> usize {
        self.data.len()
    }

    /// Get current capacity of buffer
    pub fn capacity(&self) -> usize {
        self.data.capacity()
    }
}

impl Default for Buffer {
    fn default() -> Self {
        Self::new(0)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BufferError {
    AllocationFailed,
}

impl std::fmt::Display for BufferError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            BufferError::AllocationFailed => write!(f, "Buffer allocation failed"),
        }
    }
}

impl std::error::Error for BufferError {}

GEMINI Transpilation

Overall Score: 66/100
Dimension Score Max Details
Compilation 25 25 ✓ Compiles successfully
Safety 2 20 ✗ Heavy unsafe usage (7 blocks) | ✓ Uses Result for error handling | ⚠ Uses raw pointers
Quality 20 20 ✓ Snake_case naming | ✓ Well documented (9 doc comments) | ✓ Uses ? operator | ✓ Functional programming patterns | ✓ Proper type definitions | ✓ Implementation blocks
Correctness 4 15 ✓ Edge case checks
Maintainability 5 10 ✓ Clear public API (7 items) | ✓ Uses constants
Performance 10 10 ✓ Minimal cloning | ✓ Reference usage

✅ Compilation: PASSED

Generated Rust Code (3246 bytes)

use std::alloc::{alloc, dealloc, realloc, Layout};
use std::ffi::{CStr, CString, NulError};
use std::os::raw::c_char;
use std::ptr;
use std::str;

/// Represents a dynamic buffer.
pub struct Buffer {
    data: *mut c_char,
    size: usize,
    capacity: usize,
}

impl Buffer {
    /// Initializes a new buffer with an initial capacity.
    pub fn new(initial_capacity: usize) -> Result<Self, &'static str> {
        let layout = Layout::array::<c_char>(initial_capacity).map_err(|_| "Invalid capacity")?;
        let data = unsafe { alloc(layout) as *mut c_char };

        if data.is_null() {
            return Err("Failed to allocate buffer");
        }

        unsafe {
            data.write(0 as c_char); // Null terminate
        }

        Ok(Buffer {
            data,
            size: 0,
            capacity: initial_capacity,
        })
    }

    /// Grows the buffer capacity (doubles current capacity, but at least 16).
    fn grow(&mut self) -> Result<(), &'static str> {
        let new_capacity = std::cmp::max(self.capacity * 2, 16);
        let old_layout = Layout::array::<c_char>(self.capacity).map_err(|_| "Invalid capacity")?;
        let new_layout = Layout::array::<c_char>(new_capacity).map_err(|_| "Invalid capacity")?;

        let new_data = unsafe {
            realloc(self.data as *mut u8, old_layout, new_capacity) as *mut c_char
        };

        if new_data.is_null() {
            return Err("Failed to reallocate buffer");
        }

        self.data = new_data;
        self.capacity = new_capacity;
        Ok(())
    }

    /// Appends data to the buffer.
    pub fn append(&mut self, data: &[u8]) -> Result<(), &'static str> {
        if self.size + data.len() + 1 > self.capacity {
            self.grow()?;
        }

        unsafe {
            ptr::copy_nonoverlapping(
                data.as_ptr() as *const c_char,
                self.data.add(self.size),
                data.len(),
            );
            self.size += data.len();
            self.data.add(self.size).write(0); // Null terminate
        }

        Ok(())
    }

    /// Appends a string to the buffer.
    pub fn append_str(&mut self, str: &str) -> Result<(), &'static str> {
        self.append(str.as_bytes())
    }

    /// Clears the buffer contents.
    pub fn clear(&mut self) {
        self.size = 0;
        if !self.data.is_null() {
            unsafe {
                self.data.write(0);
            }
        }
    }

    /// Returns the current buffer contents as a C string.
    pub fn c_str(&self) -> *const c_char {
        self.data as *const c_char
    }

    /// Returns the current buffer contents as a Rust String.
    pub fn to_string(&self) -> Result<String, str::Utf8Error> {
        let c_str = unsafe { CStr::from_ptr(self.c_str()) };
        c_str.to_str().map(|s| s.to_string())
    }
}

impl Drop for Buffer {
    /// Frees the buffer and its data.
    fn drop(&mut self) {
        if !self.data.is_null() {
            let layout = Layout::array::<c_char>(self.capacity).unwrap();
            unsafe {
                dealloc(self.data as *mut u8, layout);
            }
            self.data = ptr::null_mut();
            self.size = 0;
            self.capacity = 0;
        }
    }
}

Model Comparison

Model Total Compilation Safety Quality Correctness Maintainability Performance
CLAUDE 77/100 25/25 18/20 14/20 7/15 3/10 10/10
GEMINI 66/100 25/25 2/20 20/20 4/15 5/10 10/10

Evaluation Methodology

CELLO evaluates transpilation quality across 6 dimensions:

Total possible score: 100 points