diff options
Diffstat (limited to 'cpukit/libfs/src/dosfs/msdos_conv_default.c')
-rw-r--r-- | cpukit/libfs/src/dosfs/msdos_conv_default.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/cpukit/libfs/src/dosfs/msdos_conv_default.c b/cpukit/libfs/src/dosfs/msdos_conv_default.c new file mode 100644 index 0000000000..baf83208f5 --- /dev/null +++ b/cpukit/libfs/src/dosfs/msdos_conv_default.c @@ -0,0 +1,188 @@ +/** + * @file + * + * @ingroup DOSFS + * + * @brief Default Converter + */ + +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <assert.h> +#include <rtems/endian.h> +#include <rtems/dosfs.h> +#include "fat.h" +#include "msdos.h" + +static int msdos_default_utf8_to_codepage( + rtems_dosfs_convert_control *super, + const uint8_t *src, + const size_t src_size, + char *dst, + size_t *dst_size +) +{ + int eno = 0; + size_t bytes_to_copy = MIN( src_size, *dst_size ); + + (void) super; + + *dst_size = bytes_to_copy; + + memcpy( dst, src, bytes_to_copy ); + + return eno; +} + +static int msdos_default_codepage_to_utf8( + rtems_dosfs_convert_control *super, + const char *src, + const size_t src_size, + uint8_t *dst, + size_t *dst_size +) +{ + int eno = 0; + size_t bytes_to_copy = MIN( src_size, *dst_size ); + + (void) super; + + *dst_size = bytes_to_copy; + + memcpy( dst, src, bytes_to_copy ); + + return eno; +} + +static int msdos_default_utf8_to_utf16( + rtems_dosfs_convert_control *super, + const uint8_t *src, + const size_t src_size, + uint16_t *dst, + size_t *dst_size +) +{ + int eno = 0; + size_t bytes_to_copy = MIN( src_size, *dst_size / 2); + size_t i; + + (void) super; + + *dst_size = 2 * bytes_to_copy; + + for ( i = 0; eno == 0 && i < bytes_to_copy; ++i ) { + uint16_t utf16_native = src[i]; + + if ( utf16_native <= 127 ) { + dst[i] = CT_LE_W( utf16_native ); + } else { + eno = EINVAL; + } + } + + return eno; +} + +static int msdos_default_utf16_to_utf8( + rtems_dosfs_convert_control *super, + const uint16_t *src, + const size_t src_size, + uint8_t *dst, + size_t *dst_size +) +{ + int eno = 0; + size_t bytes_to_copy = MIN( src_size / 2, *dst_size ); + size_t i; + + (void) super; + + *dst_size = bytes_to_copy; + + for ( i = 0; eno == 0 && i < bytes_to_copy; ++i ) { + uint16_t utf16_le = src[i]; + uint16_t utf16_native = CF_LE_W( utf16_le ); + + if ( utf16_native <= 127 ) { + dst[i] = (uint8_t) utf16_native; + } else { + eno = EINVAL; + } + } + + return eno; +} + +static int msdos_default_normalize_and_fold( + rtems_dosfs_convert_control *super, + const uint8_t *src, + const size_t src_size, + uint8_t *dst, + size_t *dst_size +) +{ + int eno = 0; + size_t bytes_to_copy = MIN( src_size, *dst_size ); + size_t i; + + (void) super; + + *dst_size = bytes_to_copy; + + for ( i = 0; i < bytes_to_copy; ++i ) { + dst[i] = tolower( src[i] ); + } + + return eno; +} + +static void msdos_default_destroy( + rtems_dosfs_convert_control *super +) +{ + free( super ); +} + +static const rtems_dosfs_convert_handler msdos_default_convert_handler = { + .utf8_to_codepage = msdos_default_utf8_to_codepage, + .codepage_to_utf8 = msdos_default_codepage_to_utf8, + .utf8_to_utf16 = msdos_default_utf8_to_utf16, + .utf16_to_utf8 = msdos_default_utf16_to_utf8, + .utf8_normalize_and_fold = msdos_default_normalize_and_fold, + .destroy = msdos_default_destroy +}; + +typedef struct { + rtems_dosfs_convert_control super; + uint8_t buffer[MSDOS_NAME_MAX_LFN_BYTES]; +} msdos_default_convert_control; + +rtems_dosfs_convert_control *rtems_dosfs_create_default_converter(void) +{ + msdos_default_convert_control *self = malloc( sizeof( *self ) ); + + if ( self != NULL ) { + rtems_dosfs_convert_control *super = &self->super; + + super->handler = &msdos_default_convert_handler; + super->buffer.data = &self->buffer; + super->buffer.size = sizeof( self->buffer ); + } + + return &self->super; +} |