Subversion Repositories HelenOS

Rev

Rev 3886 | Rev 4243 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2009 Lukas Mejdrech
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup net
  30.  *  @{
  31.  */
  32.  
  33. /** @file
  34.  *  Character string with measured length implementation.
  35.  *  @see measured_strings.h
  36.  */
  37.  
  38. #include <errno.h>
  39. #include <malloc.h>
  40. #include <stdio.h>
  41. #include <string.h>
  42. #include <unistd.h>
  43.  
  44. #include <ipc/ipc.h>
  45.  
  46. #include "../err.h"
  47. #include "../modules.h"
  48.  
  49. #include "measured_strings.h"
  50.  
  51. /** Computes the lengths of the measured strings in the given array.
  52.  *  @param strings The measured strings array to be processed. Input parameter.
  53.  *  @param count The measured strings array size. Input parameter.
  54.  *  @returns The computed sizes array.
  55.  *  @returns NULL if there is not enough memory left.
  56.  */
  57. size_t *    prepare_lengths( const measured_string_ref strings, size_t count );
  58.  
  59. measured_string_ref measured_string_create_bulk( const char * string, size_t length ){
  60.     measured_string_ref new;
  61.  
  62.     if( length == 0 ){
  63.         while( string[ length ] ) ++ length;
  64.     }
  65.     new = ( measured_string_ref ) malloc( sizeof( measured_string_t ) + ( sizeof( char ) * ( length + 1 )));
  66.     if( ! new ) return NULL;
  67.     new->length = length;
  68.     new->value = (( char * ) new ) + sizeof( measured_string_t );
  69.     // append terminating zero explicitly - to be safe
  70.     memcpy( new->value, string, new->length );
  71.     new->value[ new->length ] = '\0';
  72.     return new;
  73. }
  74.  
  75. int measured_strings_receive( measured_string_ref * strings, char ** data, size_t count ){
  76.     ERROR_DECLARE;
  77.  
  78.     size_t *        lengths;
  79.     int             index;
  80.     size_t          length;
  81.     char *          next;
  82.     ipc_callid_t    callid;
  83.  
  84.     if(( ! strings ) || ( ! data ) || ( count <= 0 )){
  85.         return EINVAL;
  86.     }
  87.     lengths = ( size_t * ) malloc( sizeof( size_t ) * ( count + 1 ));
  88.     if( ! lengths ) return ENOMEM;
  89.     if(( ! ipc_data_write_receive( & callid, & length ))
  90.     || ( length != sizeof( size_t ) * ( count + 1 ))){
  91.         free( lengths );
  92.         return EINVAL;
  93.     }
  94.     if( ERROR_OCCURRED( ipc_data_write_finalize( callid, lengths, sizeof( size_t ) * ( count + 1 )))){
  95.         free( lengths );
  96.         return ERROR_CODE;
  97.     }
  98.     * data = malloc( lengths[ count ] );
  99.     if( !( * data )) return ENOMEM;
  100.     ( * data )[ lengths[ count ] - 1 ] = '\0';
  101.     * strings = ( measured_string_ref ) malloc( sizeof( measured_string_t ) * count );
  102.     if( !( * strings )){
  103.         free( lengths );
  104.         free( * data );
  105.         return ENOMEM;
  106.     }
  107.     next = * data;
  108.     for( index = 0; index < count; ++ index ){
  109.         ( * strings)[ index ].length = lengths[ index ];
  110.         if( lengths[ index ] > 0 ){
  111.             if(( ! ipc_data_write_receive( & callid, & length ))
  112.             || ( length != lengths[ index ] )){
  113.                 free( * data );
  114.                 free( * strings );
  115.                 free( lengths );
  116.                 return EINVAL;
  117.             }
  118.             ERROR_PROPAGATE( ipc_data_write_finalize( callid, next, lengths[ index ] ));
  119.             ( * strings)[ index ].value = next;
  120.             next += lengths[ index ];
  121.             * next = '\0';
  122.             ++ next;
  123.         }else{
  124.             ( * strings )[ index ].value = NULL;
  125.         }
  126.     }
  127.     free( lengths );
  128.     return EOK;
  129. }
  130.  
  131. int measured_strings_reply( const measured_string_ref strings, size_t count ){
  132.     ERROR_DECLARE;
  133.  
  134.     size_t *        lengths;
  135.     int             index;
  136.     size_t          length;
  137.     ipc_callid_t    callid;
  138.  
  139.     if(( ! strings ) || ( count <= 0 )){
  140.         return EINVAL;
  141.     }
  142.     lengths = prepare_lengths( strings, count );
  143.     if( ! lengths ) return ENOMEM;
  144.     if(( ! ipc_data_read_receive( & callid, & length ))
  145.     || ( length != sizeof( size_t ) * ( count + 1 ))){
  146.         free( lengths );
  147.         return EINVAL;
  148.     }
  149.     if( ERROR_OCCURRED( ipc_data_read_finalize( callid, lengths, sizeof( size_t ) * ( count + 1 )))){
  150.         free( lengths );
  151.         return ERROR_CODE;
  152.     }
  153.     free( lengths );
  154.     for( index = 0; index < count; ++ index ){
  155.         if( strings[ index ].length > 0 ){
  156.             if(( ! ipc_data_read_receive( & callid, & length ))
  157.             || ( length != strings[ index ].length )){
  158.                 return EINVAL;
  159.             }
  160.             ERROR_PROPAGATE( ipc_data_read_finalize( callid, strings[ index ].value, strings[ index ].length ));
  161.         }
  162.     }
  163.     return EOK;
  164. }
  165.  
  166. int measured_strings_return( int phone, measured_string_ref * strings, char ** data, size_t count ){
  167.     ERROR_DECLARE;
  168.  
  169.     size_t *    lengths;
  170.     int         index;
  171.     char *      next;
  172.  
  173.     if(( phone <= 0 ) || ( ! strings ) || ( ! data ) || ( count <= 0 )){
  174.         return EINVAL;
  175.     }
  176.     lengths = ( size_t * ) malloc( sizeof( size_t ) * ( count + 1 ));
  177.     if( ! lengths ) return ENOMEM;
  178.     if( ERROR_OCCURRED( ipc_data_read_start( phone, lengths, sizeof( size_t ) * ( count + 1 )))){
  179.         free( lengths );
  180.         return ERROR_CODE;
  181.     }
  182.     * data = malloc( lengths[ count ] );
  183.     if( !( * data )) return ENOMEM;
  184.     * strings = ( measured_string_ref ) malloc( sizeof( measured_string_t ) * count );
  185.     if( !( * strings )){
  186.         free( lengths );
  187.         free( * data );
  188.         return ENOMEM;
  189.     }
  190.     next = * data;
  191.     for( index = 0; index < count; ++ index ){
  192.         ( * strings )[ index ].length = lengths[ index ];
  193.         if( lengths[ index ] > 0 ){
  194.             ERROR_PROPAGATE( ipc_data_read_start( phone, next, lengths[ index ] ));
  195.             ( * strings )[ index ].value = next;
  196.             next += lengths[ index ];
  197.             * next = '\0';
  198.             ++ next;
  199.         }else{
  200.             ( * strings )[ index ].value = NULL;
  201.         }
  202.     }
  203.     free( lengths );
  204.     return EOK;
  205. }
  206.  
  207. int measured_strings_send( int phone, const measured_string_ref strings, size_t count ){
  208.     ERROR_DECLARE;
  209.  
  210.     size_t *    lengths;
  211.     int         index;
  212.  
  213.     if(( phone <= 0 ) || ( ! strings ) || ( count <= 0 )){
  214.         return EINVAL;
  215.     }
  216.     lengths = prepare_lengths( strings, count );
  217.     if( ! lengths ) return ENOMEM;
  218.     if( ERROR_OCCURRED( ipc_data_write_start( phone, lengths, sizeof( size_t ) * ( count + 1 )))){
  219.         free( lengths );
  220.         return ERROR_CODE;
  221.     }
  222.     free( lengths );
  223.     for( index = 0; index < count; ++ index ){
  224.         if( strings[ index ].length > 0 ){
  225.             ERROR_PROPAGATE( ipc_data_write_start( phone, strings[ index ].value, strings[ index ].length ));
  226.         }
  227.     }
  228.     return EOK;
  229. }
  230.  
  231. size_t * prepare_lengths( const measured_string_ref strings, size_t count ){
  232.     size_t *    lengths;
  233.     int         index;
  234.     size_t      length;
  235.  
  236.     lengths = ( size_t * ) malloc( sizeof( size_t ) * ( count + 1 ));
  237.     if( ! lengths ) return NULL;
  238.     length = 0;
  239.     for( index = 0; index < count; ++ index ){
  240.         lengths[ index ] = strings[ index ].length;
  241.         length += lengths[ index ] + 1;
  242.     }
  243.     lengths[ count ] = length;
  244.     return lengths;
  245. }
  246.  
  247. /** @}
  248.  */
  249.  
  250.