forked from len0rd/rockbox
		
	later. We still need to hunt down snippets used that are not. 1324 modified files... http://www.rockbox.org/mail/archive/rockbox-dev-archive-2008-06/0060.shtml git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17847 a1c6a512-1295-4272-9138-f99709370657
		
			
				
	
	
		
			190 lines
		
	
	
	
		
			5.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			190 lines
		
	
	
	
		
			5.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /***************************************************************************
 | |
|  *             __________               __   ___.
 | |
|  *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 | |
|  *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 | |
|  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 | |
|  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 | |
|  *                     \/            \/     \/    \/            \/
 | |
|  * $Id$
 | |
|  *
 | |
|  * Copyright (C) 2007 by Miika Pekkarinen
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU General Public License
 | |
|  * as published by the Free Software Foundation; either version 2
 | |
|  * of the License, or (at your option) any later version.
 | |
|  *
 | |
|  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 | |
|  * KIND, either express or implied.
 | |
|  *
 | |
|  ****************************************************************************/
 | |
| 
 | |
| #include <ctype.h>
 | |
| #include <string.h>
 | |
| #include <inttypes.h>
 | |
| #include "structec.h"
 | |
| #include "system.h"
 | |
| #include "file.h"
 | |
| 
 | |
| #define MAX_STRUCT_SIZE 128
 | |
| 
 | |
| /**
 | |
|  * Convert the struct endianess with the instructions provided.
 | |
|  * 
 | |
|  * For example:
 | |
|  * struct test {
 | |
|  *     long par1;
 | |
|  *     short par2;
 | |
|  *     short par3;
 | |
|  * };
 | |
|  * 
 | |
|  * structec_convert(instance_of_test, "lss", sizeof(struct test), true);
 | |
|  * 
 | |
|  * Structures to be converted must be properly padded.
 | |
|  * 
 | |
|  * @param structure Pointer to the struct being converted.
 | |
|  * @param ecinst Instructions how to do the endianess conversion.
 | |
|  * @param count Number of structures to write
 | |
|  * @param enable Conversion is not made unless this is true.
 | |
|  */
 | |
| void structec_convert(void *structure, const char *ecinst, 
 | |
|                       long count, bool enable)
 | |
| {
 | |
|     const char *ecinst_ring = ecinst;
 | |
|     char *buf = (char *)structure;
 | |
|     
 | |
|     if (!enable)
 | |
|         return;
 | |
|     
 | |
|     while (count > 0)
 | |
|     {
 | |
|         switch (*ecinst_ring)
 | |
|         {
 | |
|             /* Swap nothing. */
 | |
|             case 'c':
 | |
|             {
 | |
|                 buf++;
 | |
|                 break;
 | |
|             }
 | |
|             
 | |
|             /* Swap 2 bytes. */
 | |
|             case 's':
 | |
|             {
 | |
|                 uint16_t *data = (uint16_t *)buf;
 | |
|                 *data = swap16(*data);
 | |
|                 buf += 2;
 | |
|                 break;
 | |
|             }
 | |
| 
 | |
|             /* Swap 4 bytes. */
 | |
|             case 'l':
 | |
|             {
 | |
|                 uint32_t *data = (uint32_t *)buf;
 | |
|                 *data = swap32(*data);
 | |
|                 buf += 4;
 | |
|                 break;
 | |
|             }
 | |
|             
 | |
|             /* Skip N bytes, idea taken from metadata.c */
 | |
|             default:
 | |
|             {
 | |
|                 if (isdigit(*ecinst_ring))
 | |
|                     buf += (*ecinst_ring - '0');
 | |
| 
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         ecinst_ring++;
 | |
|         if (*ecinst_ring == '\0')
 | |
|         {
 | |
|             ecinst_ring = ecinst;
 | |
|             count--;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Determines the size of a struct in bytes by using endianess correction
 | |
|  * string format.
 | |
|  * 
 | |
|  * @param ecinst endianess correction string.
 | |
|  * @return length of the struct in bytes.
 | |
|  */
 | |
| static size_t structec_size(const char *ecinst)
 | |
| {
 | |
|     size_t size = 0;
 | |
|     
 | |
|     do
 | |
|     {
 | |
|         switch (*ecinst)
 | |
|         {
 | |
|             case 'c': size += 1; break;
 | |
|             case 's': size += 2; break;
 | |
|             case 'l': size += 4; break;
 | |
|             default: 
 | |
|                 if (isdigit(*ecinst))
 | |
|                     size += (*ecinst - '0');
 | |
|         }
 | |
|     } while (*(++ecinst) != '\0');
 | |
|     
 | |
|     return size;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Reads endianess corrected structure members from the given file.
 | |
|  * 
 | |
|  * @param fd file descriptor of the file being read.
 | |
|  * @param buf endianess corrected data is placed here.
 | |
|  * @param scount the number of struct members to read.
 | |
|  * @param ecinst endianess correction string.
 | |
|  * @param ec if true, endianess correction is enabled.
 | |
|  */
 | |
| ssize_t ecread(int fd, void *buf, size_t scount, const char *ecinst, bool ec)
 | |
| {
 | |
|     ssize_t ret;
 | |
|     size_t member_size = structec_size(ecinst);
 | |
|     
 | |
|     ret = read(fd, buf, scount * member_size);
 | |
|     structec_convert(buf, ecinst, scount, ec);
 | |
|     
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Writes endianess corrected structure members to the given file.
 | |
|  * 
 | |
|  * @param fd file descriptor of the file being written to.
 | |
|  * @param buf endianess corrected data is read here.
 | |
|  * @param scount the number of struct members to write.
 | |
|  * @param ecinst endianess correction string.
 | |
|  * @param ec if true, endianess correction is enabled.
 | |
|  */
 | |
| ssize_t ecwrite(int fd, const void *buf, size_t scount, 
 | |
|                 const char *ecinst, bool ec)
 | |
| {
 | |
|     char tmp[MAX_STRUCT_SIZE];
 | |
|     size_t member_size = structec_size(ecinst);
 | |
|     
 | |
|     if (ec)
 | |
|     {
 | |
|         const char *p = (const char *)buf;
 | |
|         int maxamount = (int)(MAX_STRUCT_SIZE / member_size);
 | |
|         int i;
 | |
|         
 | |
|         for (i = 0; i < (long)scount; i += maxamount)
 | |
|         {
 | |
|             long amount = MIN((int)scount-i, maxamount);
 | |
|             
 | |
|             memcpy(tmp, p, member_size * amount);
 | |
|             structec_convert(tmp, ecinst, amount, true);
 | |
|             write(fd, tmp, amount * member_size);
 | |
|             p += member_size * amount;
 | |
|         }
 | |
|         
 | |
|         return scount * member_size;
 | |
|     }
 | |
|     
 | |
|     return write(fd, buf, scount * member_size);
 | |
| }
 | |
| 
 |