home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c160 / 1.ddi / SOURCE / C4.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-11-19  |  13.9 KB  |  653 lines

  1.  
  2. /*  c4.c   Conversion Routines
  3.        (c)Copyright Sequiter Software Inc., 1987-1990.  All rights reserved.
  4. */
  5.  
  6. #include "d4all.h"
  7. #include "u4error.h"
  8. #include "p4misc.h"
  9.  
  10. #include <string.h>
  11. #include <ctype.h>
  12. #include <stdlib.h>
  13.  
  14. #define  JULIAN_ADJUSTMENT    1721425L
  15.  
  16.  
  17. static    char  buffer[130] ;
  18. #ifdef LANGUAGE
  19. static    char  month[][10]= {"         ",
  20.                 "Januar   ",
  21.                 "Februar  ",
  22.                 "März     ",
  23.                 "April    ",
  24.                 "Mai      ",
  25.                 "Juni     ",
  26.                 "Juli     ",
  27.                 "August   ",
  28.                 "September",
  29.                 "Oktober  ",
  30.                 "November ",
  31.                 "Dezember "
  32.               } ;
  33.  
  34. #else
  35. static    char  month[][10]= {"         ",
  36.                 "January  ",
  37.                 "February ",
  38.                 "March    ",
  39.                 "April    ",
  40.                 "May      ",
  41.                 "June     ",
  42.                 "July     ",
  43.                 "August   ",
  44.                 "September",
  45.                 "October  ",
  46.                 "November ",
  47.                 "December "
  48.               } ;
  49. #endif
  50.  
  51. /*  c4dt_format
  52.  
  53.     Formats a date from   CCYYMMDD  (Century, Year, Month, Day)
  54.     format to any date format.
  55.  
  56.     The length of 'picture' must be 32 or less.
  57.  
  58.     If there are more than 2 'M' characters in the picture, the
  59.     month will be in character form.
  60. */
  61.  
  62. char  *c4dt_format( char *dbf_date, char *picture )
  63. {
  64.    char *ptr, *ptr_end ;
  65.    int     rest, len, m_num    ;
  66.  
  67.    memset( buffer, (int) ' ', (size_t) sizeof(buffer) ) ;
  68.  
  69.    c4encode( buffer, dbf_date, picture, "CCYYMMDD") ;
  70.  
  71.    ptr_end  =  strchr( picture, 'M' ) ;
  72.    if ( ptr_end  !=  (char *) 0 )
  73.    {
  74.       ptr =  buffer+  (int) (ptr_end-picture) ;
  75.       len     =  0 ;
  76.       while ( *(ptr_end++) == 'M' )  len++ ;
  77.  
  78.       if ( len > 2)
  79.       {
  80.      /* Convert from a numeric form to character format for month */
  81.  
  82.      m_num =  c4atoi( dbf_date+4, 2) ;
  83.      if ( m_num < 0)  m_num =  1 ;
  84.      if ( m_num > 12) m_num = 12 ;
  85.  
  86.      rest =  len - 9 ;
  87.      if (len > 9) len = 9 ;
  88.  
  89.      memcpy( ptr, month[m_num], (size_t) len ) ;
  90.      if (rest > 0)    memset( ptr+len, (int) ' ', (size_t) rest ) ;
  91.       }
  92.    }
  93.    return( buffer );
  94. }
  95.  
  96.  
  97. /* Converts from formatted Date Data into '.DBF' (CCYYMMDD) format */
  98.  
  99. char  *c4dt_unformat( char *date_data, char *picture )
  100. {
  101.    char  *month_start, month_data[10] ;
  102.    int     year_count, month_count, day_count, century_count, i, len ;
  103.  
  104.    day_count    =  5 ;
  105.    month_count    =  3 ;
  106.    year_count    =  1 ;
  107.    century_count= -1 ;
  108.  
  109.    memset( buffer, (int) ' ', (size_t) 8 ) ;
  110.    buffer[8] =    '\000' ;
  111.  
  112.    for ( i=0; picture[i] != '\000'; i++ )
  113.    {
  114.       switch( picture[i] )
  115.       {
  116.      case 'D':
  117.         if ( ++day_count >= 8) break ;
  118.         buffer[day_count] =  date_data[i] ;
  119.         break ;
  120.  
  121.      case 'M':
  122.         if ( ++month_count >=6) break ;
  123.         buffer[month_count] =  date_data[i] ;
  124.         break ;
  125.  
  126.      case 'Y':
  127.         if ( ++year_count >= 4) break ;
  128.         buffer[year_count] =  date_data[i] ;
  129.         break ;
  130.  
  131.      case 'C':
  132.         if ( ++century_count >= 2) break ;
  133.         buffer[century_count] =  date_data[i] ;
  134.         break ;
  135.       }
  136.    }
  137.  
  138.    if ( strcmp( buffer, "        " ) == 0 )  return( buffer ) ;
  139.  
  140.    if ( century_count ==  -1 )    memcpy( buffer,   "19", (size_t) 2 ) ;
  141.    if ( year_count    ==   1 )    memcpy( buffer+2, "01", (size_t) 2 ) ;
  142.    if ( month_count   ==   3 )    memcpy( buffer+4, "01", (size_t) 2 ) ;
  143.    if ( day_count     ==   5 )    memcpy( buffer+6, "01", (size_t) 2 ) ;
  144.  
  145.    if ( month_count >= 6 )
  146.    {
  147.       /* Convert the Month from Character Form to Date Format */
  148.       month_start =  strchr( picture, 'M' ) ;
  149.  
  150.       len =  month_count - 3 ;    /* Number of 'M' characters in picture */
  151.  
  152.       memcpy( buffer+4, "  ", (size_t) 2 ) ;
  153.  
  154.       if ( len > 3 ) len = 3 ;
  155.       memcpy( month_data, date_data+ (int) (month_start-picture), (size_t) len) ;
  156.       while ( len > 0 )
  157.      if ( month_data[len-1] == ' ' )
  158.         len-- ;
  159.      else
  160.         break ;
  161.  
  162.       month_data[len] =  '\000' ;
  163.  
  164.       u4lower( month_data ) ;
  165.       month_data[0] =  (char) u4toupper( (int) month_data[0] ) ;
  166.  
  167.       if ( len > 0 )
  168.      for( i=1; i<= 12; i++ )
  169.      {
  170.         if ( memcmp( month[i], month_data, (size_t) len) == 0 )
  171.         {
  172.            c4ltoa( (long) i, buffer+4, 2 ) ;  /* Found Month Match */
  173.            break ;
  174.         }
  175.      }
  176.    }
  177.  
  178.    for ( i=0; i< 8; i++ )
  179.       if ( buffer[i] == ' ' )  buffer[i] =  '0' ;
  180.  
  181.    return ( buffer) ;
  182. }
  183.  
  184.  
  185. /* c4atod
  186.  
  187.    Converts a string to a double
  188. */
  189.  
  190. double c4atod( char *char_string, int string_len )
  191. {
  192.    char buffer[50] ;
  193.    int    len ;
  194.  
  195.    len =  (string_len >= 50 )  ?  49 : string_len ;
  196.    memcpy( buffer, char_string, (size_t) len ) ;
  197.    buffer[len] = '\000' ;
  198.  
  199.    return( strtod( buffer, (char **) 0)   ) ;
  200. }
  201.  
  202. /* c4atoi.c  */
  203.  
  204. int c4atoi( char *ptr,  int n)
  205. {
  206.    char buf[128] ;
  207.    if ( n >= sizeof(buf) )  n= sizeof(buf) -1 ;
  208.    memcpy(buf, ptr, (size_t) n) ;
  209.    buf[n] = '\000' ;
  210.    return (atoi(buf) ) ;
  211. }
  212.  
  213. /* c4atol  */
  214.  
  215. long c4atol( char *ptr, int n)
  216. {
  217.    char buf[128] ;
  218.    if ( n >= sizeof(buf) )  n= sizeof(buf) -1 ;
  219.    memcpy(buf, ptr, (size_t) n) ;
  220.    buf[n] = '\000' ;
  221.    return (atol(buf) ) ;
  222. }
  223.  
  224. /*  c4ltoa
  225.  
  226.     Converts a RECNUM to a string.  Fill with '0's rather than blanks if
  227.     'num' is less than zero.
  228. */
  229.  
  230. char *c4ltoa( long l_val, char *ptr, int num)
  231. {
  232.    int     n, num_pos ;
  233.    long  i_long ;
  234.  
  235.    i_long =  (l_val>0) ? l_val : -l_val ;
  236.    num_pos =  n =  (num > 0) ? num : -num ;
  237.  
  238.    while (n-- > 0)
  239.    {
  240.       ptr[n] = (char) ('0'+ i_long%10) ;
  241.       i_long = i_long/10 ;
  242.    }
  243.  
  244.    if ( i_long > 0 )
  245.    {
  246.      memset( ptr, (int) '*', (size_t) num_pos ) ;
  247.      return ptr ;
  248.    }
  249.  
  250.    num--;
  251.    for (n=0; n<num; n++)
  252.       if (ptr[n]=='0')
  253.      ptr[n]= ' ';
  254.       else
  255.      break ;
  256.  
  257.    if (l_val < 0)
  258.    {
  259.       if ( ptr[0] != ' ' )
  260.       {
  261.      memset( ptr, (int) '*', (size_t) num_pos ) ;
  262.      return ptr ;
  263.       }
  264.       for (n=num; n>=0; n--)
  265.      if (ptr[n]==' ')
  266.      {
  267.         ptr[n]= '-' ;
  268.         break ;
  269.      }
  270.    }
  271.  
  272.    return(ptr) ;
  273. }
  274.  
  275.  
  276. /* c4encode
  277.  
  278.    - From CCYYMMDD to CCYY.MM.DD
  279.  
  280.    Ex.    c4encode( to, from, "CCYY.MM.DD", "CCYYMMDD" ) ;
  281. */
  282.  
  283. void  c4encode( char *to, char *from, char *t_to, char *t_from)
  284. {
  285.    int    pos ;
  286.    char chr ;
  287.    char * chr_pos ;
  288.  
  289.    strcpy( to, t_to ) ;
  290.  
  291.    while ( (chr=*t_from++)  != 0)
  292.    {
  293.       if (  (chr_pos= strchr(t_to,chr)) ==0)
  294.       {
  295.      from++;
  296.      continue ;
  297.       }
  298.  
  299.       pos = (int) (chr_pos - t_to) ;
  300.       to[pos++] = *from++ ;
  301.  
  302.       while (chr== *t_from)
  303.       {
  304.      if (chr== t_to[pos])
  305.         to[pos++] = *from ;
  306.      t_from++ ;
  307.      from++ ;
  308.       }
  309.    }
  310. }
  311.  
  312. /* c4dtoa( doub_val, len, dec)
  313.  
  314.    - formats a double to a string
  315.    - if there is an overflow, '*' are returned
  316.  
  317.    Return
  318.  
  319.       Pointer to the Formatted String
  320. */
  321.  
  322. char * c4dtoa( double doub_val, int len, int dec)
  323. {
  324.    int     dec_val, sign_val ;
  325.    int     pre_len, post_len, sign_pos ; /* pre and post decimal point lengths */
  326.    char *result, *out_string ;
  327.  
  328.    if ( len < 0 )    len = -len  ;
  329.    if ( len > 128 )  len =  128 ;
  330.  
  331.    memset( buffer, (int) '0', (size_t) len) ;
  332.    out_string =  buffer ;
  333.  
  334.    if (dec > 0)
  335.    {
  336.       post_len =  dec ;
  337.       if (post_len > 15)     post_len =  15 ;
  338.       if (post_len > len-1)  post_len =  len-1 ;
  339.       pre_len  =  len -post_len -1 ;
  340.  
  341.       out_string[ pre_len] = '.' ;
  342.    }
  343.    else
  344.    {
  345.       pre_len  =  len ;
  346.       post_len = 0 ;
  347.    }
  348.  
  349.    result =  fcvt( doub_val, post_len, &dec_val, &sign_val) ;
  350.  
  351.    if (dec_val > 0)
  352.       sign_pos =   pre_len-dec_val -1 ;
  353.    else
  354.    {
  355.       sign_pos =   pre_len - 2 ;
  356.       if ( pre_len == 1) sign_pos = 0 ;
  357.    }
  358.  
  359.    if ( dec_val > pre_len ||  pre_len<0  ||  sign_pos< 0 && sign_val)
  360.    {
  361.       /* overflow */
  362.       memset( out_string, (int) '*', (size_t) len) ;
  363.       return( buffer) ;
  364.    }
  365.  
  366.    if (dec_val > 0)
  367.    {
  368.       memset( out_string, (int) ' ', (size_t) pre_len- dec_val) ;
  369.       memmove( out_string+ pre_len- dec_val, result, (size_t) dec_val) ;
  370.    }
  371.    else
  372.    {
  373.       if (pre_len> 0)  memset( out_string, (int) ' ', (size_t) (pre_len-1)) ;
  374.    }
  375.    if ( sign_val)  out_string[sign_pos] = '-' ;
  376.  
  377.  
  378.    out_string += pre_len+1 ;
  379.    if (dec_val >= 0)
  380.    {
  381.       result+= dec_val ;
  382.    }
  383.    else
  384.    {
  385.       out_string    -= dec_val ;
  386.       post_len += dec_val ;
  387.    }
  388.  
  389.    if ( post_len > (int) strlen(result) )
  390.       post_len =  (int) strlen( result) ;
  391.  
  392.    /*  - out_string   points to where the digits go to
  393.        - result       points to where the digits are to be copied from
  394.        - post_len     is the number to be copied
  395.    */
  396.  
  397.    if (post_len > 0)   memmove( out_string, result, (size_t) post_len) ;
  398.  
  399.    buffer[len] =  '\000' ;
  400.  
  401.    return( buffer ) ;
  402. }
  403.  
  404.  
  405. extern double floor( double ) ;
  406.  
  407. /*  static c4julian
  408.  
  409.        Returns an (int) day of the year starting from 1.
  410.        Ex.    Jan 1, returns  1
  411.  
  412.        Returns    -1  if it is an illegal date.
  413.  
  414. */
  415.  
  416. static int  month_tot[]=
  417.     { 0, 0,  31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 } ;
  418.      /* Jan Feb Mar  Apr  May  Jun    Jul  Aug  Sep  Oct  Nov  Dec
  419.          31  28  31   30   31   30     31   31   30    31   30   31
  420.      */
  421.  
  422. int c4julian( int year, int month, int day )
  423. {
  424.    int    is_leap, month_days ;
  425.  
  426.    is_leap =   ( year%4 == 0 && year%100 != 0 || year%400 == 0 ) ?  1 : 0 ;
  427.  
  428.    month_days =  month_tot[ month+1 ] -  month_tot[ month] ;
  429.    if ( month == 2 )  month_days += is_leap ;
  430.  
  431.    if ( year  < 0  ||
  432.     month < 1  ||  month > 12  ||
  433.     day   < 1  ||  day   > month_days )
  434.     return( -1 ) ;    /* Illegal Date */
  435.  
  436.    if ( month <= 2 )  is_leap = 0 ;
  437.  
  438.    return(  month_tot[month] + day + is_leap ) ;
  439. }
  440.  
  441. /*   c4ytoj -  Calculates the number of days to the year */
  442. static long  c4ytoj( int ) ;
  443.  
  444. static long  c4ytoj( int yr )
  445. {
  446.    /*
  447.        This calculation takes into account the fact that
  448.       1)  Years divisible by 400 are always leap years.
  449.       2)  Years divisible by 100 but not 400 are not leap years.
  450.       3)  Otherwise, years divisible by four are leap years.
  451.  
  452.        Since we do not want to consider the current year, we will
  453.        subtract the year by 1 before doing the calculation.
  454.    */
  455.  
  456.    yr-- ;
  457.    return( yr*365L +  yr/4L - yr/100L + yr/400L ) ;
  458. }
  459.  
  460.  
  461. /*   c4dt_julian
  462.  
  463.      Converts from database to index file date format.
  464.  
  465.      Can be used for checking the validity of a date.
  466.  
  467.      Returns
  468.     0 -  Valid Date
  469.        -1 -  Illegal Date
  470.        -2 -  NULL Date (dbf_date is all blank; converts to 1.0E100)
  471. */
  472.  
  473. int  c4dt_julian( char *dbf_date, double *index_date)
  474. {
  475.    int     year, month, day, day_year ;
  476.    long  total ;
  477.  
  478.    /* A dBASE III index file date is stored as a julian day.  That is the
  479.       number of days since the date  Jan 1, 4713 BC
  480.       Ex.  Jan 1, 1981 is  2444606
  481.    */
  482.  
  483.    year   =  c4atoi( dbf_date,     4) ;
  484.    if ( year == 0)
  485.    {
  486.       if ( memcmp( dbf_date, "        ", 8 ) == 0)
  487.       {
  488.     *index_date =  1.0E100 ;
  489.      return( -2) ;
  490.       }
  491.    }
  492.  
  493.    month  =  c4atoi( dbf_date+4, 2) ;
  494.    day      =  c4atoi( dbf_date+6, 2) ;
  495.  
  496.    day_year    =  c4julian( year, month, day) ;
  497.    if (day_year < 1)  return( -1) ;  /* Illegal Date */
  498.  
  499.    total =  c4ytoj(year) ;
  500.    total+=  day_year ;
  501.    total+=  JULIAN_ADJUSTMENT ;
  502.   *index_date  = (double) total ;
  503.  
  504.    return( 0) ;
  505. }
  506.  
  507.  
  508. /*  c4mon_dy
  509.  
  510.        Given the year and the day of the year, returns the
  511.     month and day of month.
  512. */
  513. static  int    c4mon_dy( int, int, int *, int *) ;
  514.  
  515. static int  c4mon_dy( int year, int days,  int *month_ptr,  int *day_ptr )
  516. {
  517.    int is_leap, i ;
  518.  
  519.    is_leap =  ( year%4 == 0 && year%100 != 0 || year%400 == 0 ) ?  1 : 0 ;
  520.    if ( days <= 59 )  is_leap = 0 ;
  521.  
  522.    for( i = 2; i <= 13; i++)
  523.    {
  524.       if ( days <=  month_tot[i] + is_leap )
  525.       {
  526.      *month_ptr =  --i ;
  527.      if ( i <= 2) is_leap = 0 ;
  528.  
  529.      *day_ptr   =  days - month_tot[ i] - is_leap ;
  530.      return( 0) ;
  531.       }
  532.    }
  533.    *day_ptr   =  0 ;
  534.    *month_ptr =  0 ;
  535.  
  536.    return( -1 ) ;
  537. }
  538.  
  539.  
  540. /*   c4dt_str
  541.  
  542.      Converts from the index file date format to the dbf file date format.
  543. */
  544.  
  545. void  c4dt_str( char *dbf_date, double *index_date)
  546. {
  547.    int     year, month, day, n_days, max_days ;
  548.    long  tot_days ;
  549.  
  550.    /* A dBASE III index file date is stored as a julian day.  That is the
  551.       number of days since the date  Jan 1, 4713 BC
  552.       Ex.  Jan 1, 1981 is  2444606
  553.    */
  554.  
  555.    if ( *index_date == 1.0E100 )
  556.    {
  557.       strcpy( dbf_date, "        " ) ;
  558.       return ;
  559.    }
  560.  
  561.    tot_days    =  (long) (*index_date) - JULIAN_ADJUSTMENT ;
  562.  
  563.    year        =  (int) ((double)tot_days/365.2425) + 1 ;
  564.    n_days      =  (int) (tot_days -  c4ytoj(year)) ;
  565.    if ( n_days <= 0 )
  566.    {
  567.       year-- ;
  568.       n_days   =  (int) (tot_days - c4ytoj(year)) ;
  569.    }
  570.    if (year%4 == 0 && year%100 != 0 || year%400 == 0)
  571.       max_days =  366 ;
  572.    else
  573.       max_days =  365 ;
  574.  
  575.    if ( n_days > max_days )
  576.    {
  577.       year++ ;
  578.       n_days -= max_days ;
  579.    }
  580.  
  581.    if ( c4mon_dy( year, n_days, &month, &day ) < 0 )
  582.     u4error( E_INTERNAL,"C3DT_DBF", (char *) 0 ) ;
  583.  
  584.    c4ltoa( (long) year,  dbf_date,   -4 ) ;
  585.    c4ltoa( (long) month, dbf_date+4, -2 ) ;
  586.    c4ltoa( (long) day,     dbf_date+6, -2 ) ;
  587. }
  588.  
  589. #ifdef CLIPPER
  590. /* Numeric Key Database Output is Converted to Numeric Key Index File format */
  591. c4clip( char *ptr, int len)
  592. {
  593.    int     i, negative ;
  594.    char *p ;
  595.  
  596.    for ( i= negative= 0, p= ptr; i< len; i++, p++ )
  597.    {
  598.       if ( *p == ' ' )
  599.       {
  600.      *p =  '0' ;
  601.       }
  602.       else
  603.       {
  604.      if ( *p == '-' )
  605.      {
  606.         *p =  '0' ;
  607.         negative =    1 ;
  608.      }
  609.      else
  610.         break ;
  611.       }
  612.    }
  613.  
  614.    if ( negative )
  615.    {
  616.       for ( i= 0, p= ptr; i< len; i++, p++ )
  617.      *p =  (char) 0x5c - *p ;
  618.    }
  619.  
  620.    return 0 ;
  621. }
  622. #endif
  623.  
  624. void c4trim_n( char *ptr, int num_chars )
  625. {
  626.    int    len ;
  627.  
  628.    if ( num_chars <= 0 )  return ;
  629.  
  630.    /* Count the Length */
  631.    len =  0 ;
  632.    while ( len< num_chars )
  633.    {
  634.       len++ ;
  635.       if ( *ptr++ == '\000' )  break ;
  636.    }
  637.  
  638.    if ( len < num_chars )  num_chars =    len ;
  639.  
  640.  
  641.    *(--ptr) =  '\000' ;
  642.  
  643.    while( --num_chars >= 0 )
  644.    {
  645.       ptr-- ;
  646.       if ( *ptr == '\000' ||  *ptr == ' ' )
  647.      *ptr =  '\000' ;
  648.       else
  649.      break ;
  650.    }
  651.  
  652. }
  653.