
/***************************************************************************
                                                                           *
Copyright 2013 CertiVox UK Ltd.                                           *
                                                                           *
This file is part of CertiVox MIRACL Crypto SDK.                           *
                                                                           *
The CertiVox MIRACL Crypto SDK provides developers with an                 *
extensive and efficient set of cryptographic functions.                    *
For further information about its features and functionalities please      *
refer to http://www.certivox.com                                           *
                                                                           *
* The CertiVox MIRACL Crypto SDK is free software: you can                 *
  redistribute it and/or modify it under the terms of the                  *
  GNU Affero General Public License as published by the                    *
  Free Software Foundation, either version 3 of the License,               *
  or (at your option) any later version.                                   *
                                                                           *
* The CertiVox MIRACL Crypto SDK is distributed in the hope                *
  that it will be useful, but WITHOUT ANY WARRANTY; without even the       *
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
  See the GNU Affero General Public License for more details.              *
                                                                           *
* You should have received a copy of the GNU Affero General Public         *
  License along with CertiVox MIRACL Crypto SDK.                           *
  If not, see <http://www.gnu.org/licenses/>.                              *
                                                                           *
You can be released from the requirements of the license by purchasing     *
a commercial license. Buying such a license is mandatory as soon as you    *
develop commercial activities involving the CertiVox MIRACL Crypto SDK     *
without disclosing the source code of your own applications, or shipping   *
the CertiVox MIRACL Crypto SDK with a closed source product.               *
                                                                           *
***************************************************************************/
/*
 *   MIRACL I/O routines 2. 
 *   mrio2.c
 */

#include "miracl.h"

#ifndef MR_SIMPLE_BASE
#ifndef MR_SIMPLE_IO

static void cbase(_MIPD_ big x,mr_small oldbase,big y)
{  /*  change radix of x from oldbase to base  */
    int i,s;
    mr_small n;
    BOOL done;
#ifdef MR_OS_THREADS
    miracl *mr_mip=get_mip();
#endif
    if (mr_mip->ERNUM) return;
    if (mr_mip->base==oldbase)
    {
        copy(x,y);
        return;
    }

    MR_IN(13)

    s=exsign(x);
#ifdef MR_FLASH
    numer(_MIPP_ x,mr_mip->w1);
    denom(_MIPP_ x,mr_mip->w2);
    done=FALSE;
#else
    copy(x,mr_mip->w1);
    done=TRUE;
#endif
    insign(PLUS,mr_mip->w1);

    forever
    {
        zero(mr_mip->w6);
        convert(_MIPP_ 1,mr_mip->w0);

        for (i=0;i<(int)mr_mip->w1->len;i++)  
        { /* this is a bit slow - but not time critical */


            mr_pmul(_MIPP_ mr_mip->w0,mr_mip->w1->w[i],mr_mip->w5);

            add(_MIPP_ mr_mip->w6,mr_mip->w5,mr_mip->w6);
            if (oldbase==0)
            { /* bit of a frig! */
                n=mr_shiftbits(1,MIRACL/2);
                mr_pmul(_MIPP_ mr_mip->w0,n,mr_mip->w0);
                mr_pmul(_MIPP_ mr_mip->w0,n,mr_mip->w0);
            }
            else mr_pmul(_MIPP_ mr_mip->w0,oldbase,mr_mip->w0);
        }
        if (mr_mip->ERNUM || done) break;
#ifdef MR_FLASH
        copy(mr_mip->w2,mr_mip->w1);
        copy(mr_mip->w6,mr_mip->w7);
        done=TRUE;
#endif
    }

#ifdef MR_FLASH
    fpack(_MIPP_ mr_mip->w7,mr_mip->w6,y);
#else
    copy(mr_mip->w6,y);
#endif

    insign(s,y);
    MR_OUT
}

int cinstr(_MIPD_ flash x,char *string)
{  /*  input big number in base IOBASE  */
    mr_small newb,oldb,b;
    mr_lentype lx;
    int ipt;
#ifdef MR_OS_THREADS
    miracl *mr_mip=get_mip();
#endif
    if (mr_mip->ERNUM) return 0;

    MR_IN(78)

    newb=mr_mip->IOBASE;
    oldb=mr_mip->apbase;
    mr_setbase(_MIPP_ newb); /* temporarily change base ... */
    b=mr_mip->base;
    mr_mip->check=OFF;
    ipt=instr(_MIPP_ mr_mip->w5,string); /* ... and get number  */

    mr_mip->check=ON;
    lx=(mr_mip->w5->len&MR_OBITS);
#ifdef MR_FLASH
    if ((int)(lx&MR_MSK)>mr_mip->nib || (int)((lx>>MR_BTS)&MR_MSK)>mr_mip->nib)
#else
    if ((int)lx>mr_mip->nib)
#endif
    { /* numerator or denominator too big */
        mr_berror(_MIPP_ MR_ERR_OVERFLOW);
        MR_OUT
        return 0;
    }
    mr_setbase(_MIPP_ oldb);      /* restore original base */

    cbase(_MIPP_ mr_mip->w5,b,x);

    MR_OUT
    return ipt;
}   

int cotstr(_MIPD_ flash x,char *string)
{  /*  output a big number in base IOBASE  */
    mr_small newb,oldb,b;
    int ipt;
#ifdef MR_OS_THREADS
    miracl *mr_mip=get_mip();
#endif
    if (mr_mip->ERNUM) return 0;

    MR_IN(77)
    newb=mr_mip->IOBASE;
    oldb=mr_mip->apbase;
    b=mr_mip->base;
    mr_setbase(_MIPP_ newb);   /* temporarily change base ... */
    mr_mip->check=OFF;

    cbase(_MIPP_ x,b,mr_mip->w5);   /* number may get bigger !     */   
    mr_mip->check=ON;

    ipt=otstr(_MIPP_ mr_mip->w5,string); /*..... and output number  */ 
    zero(mr_mip->w5);
    mr_setbase(_MIPP_ oldb);
    MR_OUT
    return ipt;
}

#ifndef MR_NO_FILE_IO

int cinnum(_MIPD_ flash x,FILE *filep)
{ /* convert from string to flash x */
    int n;
#ifdef MR_OS_THREADS
    miracl *mr_mip=get_mip();
#endif
    if (mr_mip->ERNUM) return 0;

    MR_IN(14)
    mr_mip->infile=filep;
    mr_mip->fin=TRUE;
    n=cinstr(_MIPP_ x,NULL);
    mr_mip->fin=FALSE;
    MR_OUT
    return n;
}

int cotnum(_MIPD_ flash x,FILE *filep)
{ /* convert flash to string */
    int n;
#ifdef MR_OS_THREADS
    miracl *mr_mip=get_mip();
#endif
    if (mr_mip->ERNUM) return 0;

    MR_IN(15)
    mr_mip->otfile=filep;
    mr_mip->fout=TRUE;
    n=cotstr(_MIPP_ x,NULL);
    mr_mip->fout=FALSE;
    MR_OUT
    return n;
}

#endif

#endif
#endif
