Logo Search packages:      
Sourcecode: jack-tools version File versions  Download package

osc.c

#ifndef _OSC_C
#define _OSC_C

#include <stdio.h>
#include <string.h>
#include "byte-order.c"

typedef union
{
  int32_t i ;
  int64_t h ;
  uint64_t t ;
  float32_t f ;
  float64_t d ;
  const char *s ;
  const char *S ;
  uint32_t c ;
  uint32_t m ;
  uint32_t r ;
  struct { const char *data ; int32_t size ; } b ;
}
osc_data_t ;
  
void
osc_print_packet ( const char *packet , int32_t packet_sz )
{
  int32_t i ;
  for ( i = 0 ; i < packet_sz ; i++ ) {
    fprintf ( stderr , "%3d (%1.1s) " , packet[i] , packet + i ) ;
    if ( ( i + 1 ) % 4  == 0 ) {
      fprintf ( stderr , "\n" ) ;
    }
  }
}
    
inline int32_t
osc_str_bound ( int32_t n )
{
  return n + ( 4 - ( n % 4 ) ) ;
}

inline int
osc_is_numerical_type ( char c ) 
{
  return c == 'i' || c == 'h' || c == 't' || c == 'f' || c == 'd' ;
}

inline int
osc_is_string_type ( char c ) 
{
  return c == 's' || c == 'S' ;
}

inline int
osc_can_coerce ( char u , char d ) 
{
  return ( ( u == d ) ||
         ( osc_is_numerical_type ( u ) && osc_is_numerical_type ( d ) ) ||
         ( osc_is_string_type ( u ) && osc_is_string_type ( d ) ) ) ;
}

inline void
osc_coerce ( char u , char d , osc_data_t *o )
{
  if ( u == d ) {
    return ;
  }
  if ( u == 's' && d == 'S' ) {
    o->s = o->S ;
  } else if ( u == 'S' && d == 's' ) {
    o->S = o->s ;
  } else if ( u == 'i' && d == 'h' ) {
    o->i = (int32_t) o->h ;
  } else if ( u == 'i' && d == 't' ) {
    o->i = (int32_t) o->t ;
  } else if ( u == 'i' && d == 'f' ) {
    o->i = (int32_t) floorf ( o->f ) ;
  } else if ( u == 'i' && d == 'd' ) {
    o->i = (int32_t) floor ( o->d ) ;
  } else if ( u == 'h' && d == 'i' ) {
    o->h = (int64_t) o->i ;
  } else if ( u == 'h' && d == 't' ) {
    o->h = (int64_t) o->t ;
  } else if ( u == 'h' && d == 'f' ) {
    o->h = (int64_t) floorf ( o->f ) ;
  } else if ( u == 'h' && d == 'd' ) {
    o->h = (int64_t) floor ( o->d ) ;
  } else if ( u == 't' && d == 'i' ) {
    o->t = (uint64_t) o->i ;
  } else if ( u == 't' && d == 'h' ) {
    o->t = (uint64_t) o->t ;
  } else if ( u == 't' && d == 'f' ) {
    o->t = (uint64_t) floorf ( o->f ) ;
  } else if ( u == 't' && d == 'd' ) {
    o->t = (uint64_t) floor ( o->d ) ;
  } else if ( u == 'f' && d == 'i' ) {
    o->f = (float32_t) o->i ;
  } else if ( u == 'f' && d == 'h' ) {
    o->f = (float32_t) o->h ;
  } else if ( u == 'f' && d == 't' ) {
    o->f = (float32_t) o->t ;
  } else if ( u == 'f' && d == 'd' ) {
    o->f = (float32_t) o->d ;
  } else if ( u == 'd' && d == 'i' ) {
    o->d = (float64_t) o->i ;
  } else if ( u == 'd' && d == 'h' ) {
    o->d = (float64_t) o->h ;
  } else if ( u == 'd' && d == 't' ) {
    o->d = (float64_t) o->t ;
  } else if ( u == 'd' && d == 'f' ) {
    o->d = (float64_t) o->d ;
  } else {
    fprintf ( stderr , "osc_coerce: illegal coercion '%c' <- '%c'\n" , u , d ) ;
    FAILURE ;
  }
}

inline void
osc_coerce_arguments ( const char *u_dsc , const char *p_dsc , osc_data_t *data )
{
  u_dsc++ ;
  p_dsc++ ;
  while ( *u_dsc != '\0' ) {
    osc_coerce ( *u_dsc++ , *p_dsc++ , data++ ) ;
  }
}

inline int
osc_collect_arguments ( const char *dsc , const char *p , osc_data_t *data )
{
  dsc++ ;
  int i = 0 ;
  while ( *dsc != '\0' ) {
    char c = *dsc ;
    if ( c == 'i' ) {
      data[i].i = ntoh_int32_from_buf ( p ) ;
      p += 4 ;
    } else if ( c == 'h' ) {
      data[i].h = ntoh_int64_from_buf ( p ) ;
      p += 8 ;
    } else if ( c == 't' ) {
      data[i].t = ntoh_uint64_from_buf ( p ) ;
      p += 8 ;
    } else if ( c == 'f' ) {
      data[i].f = ntoh_float32_from_buf ( p ) ;
      p += 4 ; 
    } else if ( c == 'd' ) {
      data[i].d = ntoh_float64_from_buf ( p ) ;
      p += 8 ; 
    } else if ( c == 's' ) {
      data[i].s = p ;
      p += osc_str_bound ( strlen ( p ) ) ;
    } else if ( c == 'S' ) {
      data[i].S = p ;
      p += osc_str_bound ( strlen ( p ) ) ;
    } else if ( c == 'c' ) {
      data[i].c = ntoh_uint32_from_buf ( p ) ;
      p += 4 ; 
    } else if ( c == 'm' ) {
      data[i].m = ntoh_uint32_from_buf ( p ) ;
      p += 4 ; 
    } else if ( c == 'r' ) {
      data[i].r = ntoh_uint32_from_buf ( p ) ;
      p += 4 ; 
    } else if ( c == 'b' ) {
      data[i].b.data = p + 4 ;
      data[i].b.size = ntoh_int32_from_buf ( p ) ;
      p += data[i].b.size + 4 ;
    } else {
      return -1 ;
    }
    dsc++ ;
    i++ ;
  }
  return 0 ;
}

inline int32_t
osc_dsc_read_arg_len ( const char *dsc , const char *p )
{
  if ( *dsc++ != ',' ) {
    fprintf ( stderr , "osc_dsc_read_arg_len: illegal descriptor '%s'\n" , dsc ) ;
    return -1 ;
  }
  int32_t n = 0 ;
  while ( *dsc != '\0' ) {
    char c = *dsc ;
    if ( c == 'i' || c == 'f' || c == 'c' || c == 'm' || c == 'r' ) {
      n += 4 ; 
    } else if ( c == 'd' || c == 'h' || c == 't' ) {
      n += 8 ;
    } else if ( c == 's' || c == 'S' ) {
      n += osc_str_bound ( strlen ( p + n ) ) ;
    } else if ( c == 'b' ) {
      n += ntoh_int32_from_buf ( p + n ) + 4 ;
    } else {
      return -1 ;
    }
    dsc++ ;
  }
  return n ;
}

inline const char *
osc_message_dsc ( const char *packet ) 
{
  return packet + osc_str_bound ( strlen ( packet ) ) ;
}


inline int32_t
osc_match_address ( const char *addr , const char *packet )
{
  size_t addr_n = strlen ( addr ) ;
  if ( strncmp ( addr , packet , addr_n ) != 0 ) {
    return 0 ;
  } else {
    return osc_str_bound ( addr_n ) ;
  }
}

inline int32_t
osc_match_dsc ( const char *u_dsc , const char *p_dsc )
{
  size_t u_dsc_n = strlen ( u_dsc ) ;
  if ( *u_dsc++ != ',' || *p_dsc++ != ',' ) {
    return 0 ;
  }
  while ( *u_dsc != '\0' ) {
    if ( ! osc_can_coerce ( *u_dsc++ , *p_dsc++ ) ) {
      return 0 ;
    }
  }
  return osc_str_bound ( u_dsc_n ) ;
}

int32_t
osc_parse_message ( const char *addr , const char *dsc , const char *packet , int32_t packet_sz , osc_data_t *data )
{
  int32_t addr_len = osc_match_address ( addr , packet ) ;
  if ( ! addr_len ) {
    return 0 ;
  }
  const char *p_dsc = packet + addr_len ;
  int32_t dsc_len = osc_match_dsc ( dsc , p_dsc ) ;
  if ( ! dsc_len ) {
    return 0 ;
  }
  const char *p_arg = p_dsc + dsc_len ;
  int32_t arg_len = osc_dsc_read_arg_len ( p_dsc , p_arg ) ;
  if ( packet_sz < addr_len + dsc_len + arg_len ) {
    return 0 ;
  }
  int err = osc_collect_arguments ( p_dsc , p_arg , data ) ;
  if ( err ) {
    return 0 ;
  }
  osc_coerce_arguments ( dsc , p_dsc , data ) ;
  return addr_len + dsc_len + arg_len ;
}

inline int
osc_pack_arguments ( const char *dsc , const osc_data_t *data , char *p )
{
  dsc++ ;
  int i = 0 ;
  while ( *dsc != '\0' ) {
    char c = *dsc ;
    if ( c == 'i' ) {
      ntoh_int32_to_buf ( p , data[i].i ) ;
      p += 4 ;
    } else if ( c == 'h' ) {
      ntoh_int64_to_buf ( p , data[i].h ) ;
      p += 8 ;
    } else if ( c == 't' ) {
      ntoh_uint64_to_buf ( p , data[i].t ) ;
      p += 8 ;
    } else if ( c == 'f' ) {
      ntoh_float32_to_buf ( p , data[i].f ) ;
      p += 4 ; 
    } else if ( c == 'd' ) {
      ntoh_float64_to_buf ( p , data[i].d ) ;
      p += 8 ; 
    } else if ( c == 's' ) {
      strcpy ( p , data[i].s ) ;
      p += osc_str_bound ( strlen ( data[i].s ) ) ;
    } else if ( c == 'S' ) {
      strcpy ( p , data[i].S ) ;
      p += osc_str_bound ( strlen ( data[i].S ) ) ;
    } else if ( c == 'c' ) {
      ntoh_uint32_to_buf ( p , data[i].c ) ;
      p += 4 ; 
    } else if ( c == 'm' ) {
      ntoh_uint32_to_buf ( p , data[i].m ) ;
      p += 4 ; 
    } else if ( c == 'r' ) {
      ntoh_uint32_to_buf ( p , data[i].r ) ;
      p += 4 ; 
    } else if ( c == 'b' ) {
      ntoh_int32_to_buf ( p , data[i].b.size ) ;
      memcpy ( p + 4 , data[i].b.data , data[i].b.size ) ;
      p += data[i].b.size + 4 ;
    } else {
      return -1 ;
    }
    dsc++ ;
    i++ ;
  }
  return 0 ;
}

inline int32_t
osc_dsc_calculate_arg_len ( const char *dsc , const osc_data_t *data )
{
  if ( *dsc++ != ',' ) {
    fprintf ( stderr , "osc_dsc_calculate_arg_len: illegal descriptor '%s'\n" , dsc ) ;
    return -1 ;
  }
  int32_t n = 0 ;
  while ( *dsc != '\0' ) {
    char c = *dsc ;
    if ( c == 'i' || c == 'f' || c == 'c' || c == 'm' || c == 'r' ) {
      n += 4 ; 
    } else if ( c == 'd' || c == 'h' || c == 't' ) {
      n += 8 ;
    } else if ( c == 's' ) {
      n += osc_str_bound ( strlen ( data->s ) ) ;
    } else if ( c == 'S' ) {
      n += osc_str_bound ( strlen ( data->S ) ) ;
    } else if ( c == 'b' ) {
      n += data->b.size + 4 ;
    } else {
      return -1 ;
    }
    dsc++ ;
    data++ ;
  }
  return n ;
}

int32_t
osc_construct_message ( const char *addr , const char *dsc , const osc_data_t *data , char *packet , int32_t packet_sz )
{
  int32_t addr_len = osc_str_bound ( strlen ( addr ) ) ;
  int32_t dsc_len = osc_str_bound ( strlen ( dsc ) ) ;
  int32_t arg_len = osc_dsc_calculate_arg_len ( dsc , data ) ;
  memset ( packet , 0 , addr_len + dsc_len + arg_len ) ;
  strcpy ( packet , addr ) ;
  strcpy ( packet + addr_len , dsc ) ;
  if ( packet_sz < addr_len + dsc_len + arg_len ) {
    return 0 ;
  }
  int err = osc_pack_arguments ( dsc , data , packet + addr_len + dsc_len ) ;
  if ( err ) {
    return 0 ;
  }
  return addr_len + dsc_len + arg_len ;
}

#endif

Generated by  Doxygen 1.6.0   Back to index