Subtitle Resynchronizer (II)

It is revealed that this code doesn't worth the time I spent once it is done.
The code of rangemap.h is not provided. It is the most unqualified for being part of the lib.

#include <cassert>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <string>
#include <list>
#include <conio.h>

#include <qtl/ctnr/rangemap.h>

#define GENUSE_BUFSIZE    1024


using namespace std;
using namespace qtl;


typedef unsigned long    movtime_t;

struct TimeMapTraits : public RangeMapTraits<movtime_t>
{
    static bool DoMapSToD (TsCref sIni, TsCref sEnd, TdCref dIni, TdCref dEnd,
        bool rev, TsCref s, TdRef d)
    {
        d = (s - sIni) + dIni;
        return true;
    }

    static bool DoMapDToS (TdCref dIni, TdCref dEnd, TsCref sIni, TsCref sEnd,
        bool rev, TdCref d, TsRef s)
    {
        s = (d - dIni) + sIni;
        return true;
    }
};

struct TimeMap : public SegRangeMap<movtime_t, movtime_t, TimeMapTraits>
{
private:
    typedef SegRangeMap<movtime_t, movtime_t, TimeMapTraits>    MyBase;

public:
    LsItr   recent;

    struct DstRange
    {
        movtime_t   ini, end;
        DstRange (movtime_t i, movtime_t e) : ini(i), end(e) {}
    };

    typedef vector<DstRange>    DrVec;

    TimeMap ()
    {
        Clear();
    }

    void Clear ()
    {
        MyBase::Clear();
        InitRecent();
    }

    void InitRecent()
    {
        recent = listS.begin();
    }

    bool MapSToD (TsCref s, OutVecD &ds)
    {
        LsItr   itr;
        bool    found = false;
        ds.clear();
        LsItr   begin = recent;
        LsItr   end = listS.end();
        movtime_t    d;
        LsItr   newRecent;

        // backward
        for (itr = recent; itr != listS.begin();)
        {
            itr--;
            if (TrySToD(*itr, s, d))
            {
                ds.push_back(d);
                found = true;
                newRecent = recent;
            }
            else if (s >= itr->end)
            {
                break;
            }
        }
        // forward
        for (itr = recent; itr != listS.end(); ++itr)
        {
            if (TrySToD(*itr, s, d))
            {
                ds.push_back(d);
                if (!found)
                {
                    newRecent = recent;
                    found = true;
                }
            }
            else if (s < itr->ini)
            {
                break;
            }
        }

        if (found)
        {
            recent = newRecent;
        }
        return found;
    }

    bool MapRangeSToD (TsCref sIni, TsCref sEnd, DrVec &drs)
    {
        OutVecD ds;
        if (!MapSToD(sIni, ds))
        {
            return false;
        }
        movtime_t d = sEnd - sIni;

        drs.clear();
        for (int i = 0; i < ds.size(); i++)
        {
            movtime_t ini = ds[i];
            movtime_t end = ini + d;
            int j;
            for (j = 0; j < drs.size(); j++)
            {
                if (drs[j].ini > ini)
                {
                    break;
                }
            }
            
            drs.insert(drs.begin() + j, DstRange(ini, end));
        }

        return true;
    }
};

/* Sub to abs time (many to one) mapping */
typedef TimeMap SubToAbsMap;

/* Mov to abs time (one to many) mapping */
typedef TimeMap AbsToMovMap;


struct SubMovMapper
{
    SubToAbsMap        stoa;
    AbsToMovMap        atom;

    typedef AbsToMovMap::OutVecD    OutVec;
    typedef AbsToMovMap::DrVec        DrVec;
    typedef AbsToMovMap::DstRange    DstRange;

    void AddSubToAbs (movtime_t sIni, movtime_t sEnd, movtime_t aIni, movtime_t aEnd)
    {
        stoa.AddMap(sIni, sEnd, aIni, aEnd);
    }

    void AddAbsToMov (movtime_t aIni, movtime_t aEnd, movtime_t mIni, movtime_t mEnd)
    {
        atom.AddMap(aIni, aEnd, mIni, mEnd);
    }

    bool MapSubToAbs (movtime_t s, movtime_t &a)
    {
        SubToAbsMap::OutVecD as;
        if (!stoa.MapSToD(s, as)) return false;
        a = as[0];
        return true;
    }

    bool MapAbsToMov (movtime_t a, OutVec &m)
    {
        return atom.MapSToD(a, m);
    }

    bool MapSubToMov (movtime_t s, OutVec &m)
    {
        movtime_t a;
        if (!MapSubToAbs(s, a)) return false;
        return MapAbsToMov(a, m);
    }

    bool MapRangeSubToAbs (movtime_t sIni, movtime_t sEnd, movtime_t &dIni, movtime_t &dEnd)
    {
        SubToAbsMap::DrVec  drs;
        if (!stoa.MapRangeSToD(sIni, sEnd, drs)) return false;
        dIni = drs[0].ini;
        dEnd = drs[0].end;
        return true;
    }

    bool MapRangeAbsToMov (movtime_t sIni, movtime_t sEnd, DrVec &drs)
    {
        return atom.MapRangeSToD(sIni, sEnd, drs);
    }

    void Clear ()
    {
        stoa.Clear();
        atom.Clear();
    }

    void InitRecent ()
    {
        stoa.InitRecent();
        atom.InitRecent();
    }
};


struct CommonParser
{
    static int ReadAsManyDigits (const char *&psz, unsigned long &val)
    {
        int r;
        val = 0;
        if (psz[0] == 0)
        {
            return 0;
        }
        for (r = 0 ; psz[0] >= '0' && psz[0] <= '9'; ++psz)
        {
            val *= 10;
            val += psz[0] - '0';
            r++;
        }
        return r;
    }

    static bool GoUntil (const char *&psz, const char *csz)
    {
        const char *pcsz = csz;
        for ( ; *psz != 0 && *pcsz != 0; psz++)
        {
            if (*psz == *pcsz)
            {
                pcsz++;
            }
            else
            {    /* unfortunately it's not kmp */
                psz -= pcsz - csz;
                pcsz = csz;
            }
        }

        return *pcsz == 0;
    }

    static void SkipBlanks (const char *&psz)
    {
        for ( ; psz[0] == ' ' || psz[0] == '/t'; ++psz);
    }

    static bool Pass (const char *&psz, const char *csz)
    {
        SkipBlanks(psz);
        for ( ; *csz != 0 && *psz == *csz; psz++, csz++);
        SkipBlanks(psz);
        return (*csz == 0);
    }
};

struct TmapParser : public CommonParser
{
    typedef vector<movtime_t>    TimeVec;

    TimeVec        baseTime;
    TimeVec        volDur;            // explicitly indicated volumn duration
    movtime_t    oldst, olddt;

    enum PlusType
    {
        k_ptNormal,
        k_ptPrevious,
        k_ptExpected,
    };

    TmapParser ()
    {
        SetNumVols(0);
    }

    static bool ParseDigitalTime (const char *&psz, movtime_t &ot, int *pVol = 0)
    {
        unsigned long val;
        unsigned long hr, min, sec, msec;
        int vol = -1;
        int len = ReadAsManyDigits(psz, val);
        if (len == 0) return false;
        if (psz[0] == '.')
        {
            if (val == 0)
            {
                return false;
            }
            vol = val - 1;    // volumne number starts from 1
        }
        else if (psz[0] == ':')
        {
            hr = val;
        }
        else
        {
            ot = val;
            return true;
        }

        if (vol >= 0)
        {
            psz++;
            len = ReadAsManyDigits(psz, hr);
            if (len == 0 || psz[0] != ':') return false;
        }

        psz++;
        len = ReadAsManyDigits(psz, min);
        if (len == 0 || psz[0] != ':') return false;
        psz++;
        len = ReadAsManyDigits(psz, sec);
        if (len == 0) return false;
        if (psz[0] == ',')
        {
            psz++;
            len = ReadAsManyDigits(psz, msec);
        }

        ot = ((hr * 60+min)*60+sec)*1000+msec;

        if (pVol)
        {
            *pVol = vol;
        }

        return true;
    }

    bool ParseTime (const char *&psz, movtime_t &ot, PlusType &plus)
    {
        int vol = -1, hr, min, sec, msec;

        int len;
        movtime_t            t;
        vector<movtime_t>    vt;
        vector<bool>        st;
        int                    sig = 1;
        bool                expectnote= true;
        bool                expectval = true;

        plus = k_ptNormal;

        // overflow doesn't fail the result
        ot = 0;
        while (1)
        {
            SkipBlanks(psz);
            if (psz[0] == '+' && expectnote)
            {
                sig = 1;
                expectnote = false; expectval = true;
                psz++;
            }
            else if (psz[0] == '-' && expectnote)
            {
                sig = -1;
                expectnote = false; expectval = true;
                psz++;
            }
            else if ((psz[0] == '^' || psz[0] == '*') && expectval)
            {
                if (sig < 0) { return false; }
                if (plus != k_ptNormal)
                {
                    return false;
                }
                plus = psz[0] == '^'? k_ptPrevious : k_ptExpected;
                expectval = false; expectnote = true;
                ++psz;
            }
            else if (expectval)
            {
                if (!ParseDigitalTime(psz, t, &vol))
                {
                    return false;
                }

                if (vol >= 0)
                {
                    int    numVols = baseTime.size();
                    if (vol >= numVols)
                    {
                        return false;
                    }
                    t += baseTime[vol];

                    if (vol + 1 < numVols && baseTime[vol+1] < t)
                    {
                        baseTime[vol+1] = t;    // default base time for next volume
                        if (baseTime[vol+1] - baseTime[vol] < volDur[vol])
                        {
                            baseTime[vol+1] = baseTime[vol] + volDur[vol];
                        }
                    }
                }

                printf("t=%d/n", t);
                st.push_back(sig);
                vt.push_back(t);
                if (sig>0)
                {
                    ot += t;
                }
                else
                {
                    ot -= t;
                }
                expectval = false; expectnote = true;
            }
            else
            {
                break;
            }
        }
        if (expectval == true)
        {    // syntax error
            return false;
        }
        
        return true;
    }

    bool ParseTmapLine (const char *szLine, movtime_t &st1, movtime_t &st2,
            movtime_t &dt1, movtime_t &dt2)
    {
        int val;
        const char *psz = szLine;
        PlusType plus[4];

        if (!ParseTime(psz, st1, plus[0])) return false;
        if (plus[0] == k_ptPrevious)
        {
            st1 += oldst;
        }
        if (!Pass(psz, "~")) return false;
        if (!ParseTime(psz, st2, plus[1])) return false;
        if (plus[1] == k_ptPrevious)
        {
            st2 += oldst;
        }

        
        if (!Pass(psz, "=>")) return false;

        if (!ParseTime(psz, dt1, plus[2])) return false;
        if (plus[2] == k_ptPrevious)
        {
            dt1 += olddt;
        }
        if (!Pass(psz, "~")) return false;
        if (!ParseTime(psz, dt2, plus[3])) return false;
        if (plus[3] == k_ptPrevious)
        {
            dt2 += olddt;
        }

        int plusexp, i;
        for (plusexp = 0, i = 0; i < 4; i++)
        {
            if (plus[i] == k_ptExpected)
            {
                plusexp++;
            }
        }
        if (plusexp > 1)
        {
            return false;
        }

        if (plus[0] == k_ptExpected)
        {
            st1 += st2 - (dt2 - dt1);
        }
        else if (plus[1] == k_ptExpected)
        {
            st2 += st1 + (dt2 - dt1);
        }
        else if (plus[2] == k_ptExpected)
        {
            dt1 += dt2 - (st2 - st1);
        }
        else if (plus[3] == k_ptExpected)
        {
            dt2 += dt1 + (st2 - st1);
        }

        oldst = st2;
        olddt = dt2;

        return true;
    }

    void SetNumVols (int n)
    {
        baseTime.resize(n, 0);
        volDur.resize(n, 0);
        oldst = olddt = 0;
    }

    void SetVolDur (int i, movtime_t d)
    {
        volDur[i] = d;
    }

};

struct StResync
{
    struct Item
    {
        movtime_t    absini;
        movtime_t    absend;
        char        strbuf[GENUSE_BUFSIZE];
    };

    SubMovMapper    mapper;

    struct In
    {
        TmapParser        parser;
        SubMovMapper    *pMapper;

        vector<FILE *>    files;
        int                fvidx;

        bool            isEnd;
        
        int                sn;

        In (SubMovMapper *pm) : pMapper(pm)
        {
            Clear();
        }

        ~In ()
        {
            for (int i = 0; i < files.size(); i++)
            {
                if (files[i])
                {
                    fclose(files[i]);
                }
            }
        }

        void Clear ()
        {
            fvidx = 0;
            isEnd = false;
            sn = -1;
            parser.SetNumVols(0);
            files.clear();
        }

        bool IsSn (const char *buf, int &sn) const
        {
            const char *psz = buf;
            unsigned long val;
            int len = CommonParser::ReadAsManyDigits(psz, val);
            if (len == 0 || psz[0] != 0)
            {
                return false;
            }
            sn = val;
            return true;
        }

        bool Get (Item &item)
        {
            char    buf[GENUSE_BUFSIZE];

        __again:
            if (sn < 0)
            {
                do
                {
                    if (!StResync::GetLine(buf, GENUSE_BUFSIZE, files[fvidx])) return false;
                } while (!IsSn(buf, sn));
            }

            if (!StResync::GetLine(buf, GENUSE_BUFSIZE, files[fvidx])) return false;

            movtime_t ini, end;
            const char *psz = buf;    // use it at present for holding data
            TmapParser::SkipBlanks(psz);
            if (!TmapParser::ParseDigitalTime(psz, ini)) return false;
            TmapParser::SkipBlanks(psz);
            TmapParser::Pass(psz, "-->");
            TmapParser::SkipBlanks(psz);
            if (!TmapParser::ParseDigitalTime(psz, end)) return false;
            TmapParser::SkipBlanks(psz);


            ini += parser.baseTime[fvidx];
            end += parser.baseTime[fvidx];
    

            if (!pMapper->MapRangeSubToAbs(ini, end, item.absini, item.absend)) return false;

            sn = -1;
            item.strbuf[0] = 0;
            int fileCount = files.size();
            while (1)
            {    /* content */
                if (!StResync::GetLine(buf, GENUSE_BUFSIZE, files[fvidx]))
                {
                    fvidx++;
                    if (fvidx < fileCount) continue;
                    isEnd = true;
                    return false;
                }

                if (IsSn(buf, sn))
                {
                    break;
                }

                strcat(item.strbuf, buf);
                strcat(item.strbuf, "/n");
            }

            if (item.absini == item.absend)
            {
                goto __again;
            }

            return true;
        }

        bool IsEnd ()
        {
            return isEnd;
        }

        void SetNumVols (int n)
        {
            parser.SetNumVols(n);
            files.resize(n);
            fvidx = 0;
        }

        void AddFile (int i, FILE *f, movtime_t dur)
        {
            files[i] = f;
            parser.SetVolDur(i, dur);
        }
    };

    struct Out
    {
        TmapParser            parser;
        SubMovMapper        *pMapper;

        vector<FILE *>        files;
        vector<movtime_t>    baseTime;
        vector<int>            sns;
        int                    fvidx;

        Out (SubMovMapper *pm) : pMapper(pm)
        {
            Clear();
        }

        ~Out ()
        {
            for (int i = 0; i < files.size(); i++)
            {
                if (files[i])
                {
                    fclose(files[i]);
                }
            }
        }

        void Clear ()
        {
            SetNumVols(0);
        }

        static void AnalyseTime (movtime_t t, int &h, int &m, int &s, int &ms)
        {
            ms = t % 1000;
            t /= 1000;
            s = t % 60;
            t /= 60;
            m = t % 60;
            t /= 60;
            h = t;
        }

        bool Set (Item &item)
        {
            char tempbuf[64] = {0, };
            char outbuf[GENUSE_BUFSIZE] = {0, };

            SubMovMapper::DrVec    movrs;

            if (!pMapper->MapRangeAbsToMov(item.absini, item.absend, movrs))
            {   // no matching time segment in the movie
                return false;
            }

            int n = movrs.size();
            int fn = files.size();

            static int lastI;

            for (int i = 0; i < n; i++)
            {
                movtime_t ini = movrs[i].ini;
                movtime_t end = movrs[i].end;
                int fvibegin = fvidx;
                int fviend = fvidx;

                for (fvibegin = 0; fvibegin < fn && ini < baseTime[fvibegin]; fvibegin++)
                {
                }
                for ( ; fvibegin + 1 < fn && ini >= baseTime[fvibegin + 1]; fvibegin++)
                {
                }

                ini -= baseTime[fvibegin];
                fviend = fvibegin;  // can only be too small

                for ( ; fviend+1 < fn && end > baseTime[fviend+1]; fviend++)
                {
                }
                /*
                for ( ; fviend > 0 && end <= baseTime[fviend]; fvend--)
                {
                }
                */
                end -= baseTime[fviend];

                for (int i = fvibegin; i <= fviend; i++)
                {
                    movtime_t vi, ve;
                    if (i == fvibegin)
                    {
                        vi = ini;
                    }
                    else
                    {
                        vi = 0;
                    }
                    if (i == fviend)
                    {
                        ve = end;
                    }
                    else
                    {
                        ve = baseTime[i + 1] - baseTime[i];
                    }


                    // SN
                    sprintf(outbuf, "%d/n", ++sns[i]);

                    // Time stamp
                    int h, m, s, ms;
                    AnalyseTime(vi, h, m, s, ms);
                    sprintf(tempbuf, "%02d:%02d:%02d,%03d", h, m, s, ms);
                    strcat(outbuf, tempbuf);
                    AnalyseTime(ve, h, m, s, ms);
                    sprintf(tempbuf, " --> %02d:%02d:%02d,%03d/n", h, m, s, ms);
                    strcat(outbuf, tempbuf);

                    // Text
                    strcat(outbuf, item.strbuf);

                    fprintf(files[i], "%s", outbuf);        
                }
            }

            return true;
        }

        void SetNumVols (int n)
        {
            files.resize(n, 0);
            baseTime.resize(n, 0);
            sns.resize(n, 0);
            parser.SetNumVols(n);
            fvidx = 0;
        }

        void AddFile (int i, FILE *f, movtime_t dur)
        {
            files[i] = f;
            if (i == 0)
            {
                baseTime[i] = 0;
            }
            if (i < baseTime.size() - 1)
            {
                baseTime[i+1] = baseTime[i] + dur;
            }
            parser.SetVolDur(i, dur);
        }

    };

    In    in;
    Out    out;

    StResync () : in(&mapper), out(&mapper)
    {
    }

    static bool GetLine (char *buf, int bufsize, FILE *f)
    {
        if (feof(f))
        {
            return false;
        }
        buf[0] = 0;
        fgets(buf, bufsize, f);
        int len = strlen(buf);
        if (len>0 && buf[len-1]==0xa) len--;
        if (len>0 && buf[len-1]==0xd) len--;
        buf[len] = 0;
        return true;
    }

    static const char *ProcessFileInfo(char *buf, movtime_t &dur)
    {
        const char *psz = buf;
        CommonParser::SkipBlanks(psz);
        const char *psz2 = psz;
        if (CommonParser::GoUntil(psz2, ">>"))
        {
            const char *psz3 = psz2;
            psz2 -= 2;
            if (psz == psz2)
            {
                return 0;
            }
            for ( ; psz2[-1] == ' ' || psz2[-1] == '/t'; psz2--)
            {
            }
            char *psz4 = const_cast<char *>(psz2);
            psz4[0] = 0;
            
            CommonParser::SkipBlanks(psz3);
            if (!TmapParser::ParseDigitalTime(psz3, dur))
            {
                return 0;
            }
        }

        return psz;
    }

    static bool IsEmptyLine (const char *buf)
    {
        const char *psz = buf;
        CommonParser::SkipBlanks(psz);
        return psz[0] == 0;
    }

    static bool IsSepLine (const char *buf)
    {
        const char *psz = buf;
        CommonParser::SkipBlanks(psz);
        return (psz[0] == '*' && psz[1] == '*' && psz[1] == '*');
    }

    bool ParseConfig (FILE *fConfig)
    {
        char buf[GENUSE_BUFSIZE];
        const char *psz;
        int len;
        unsigned long n;

        in.Clear();
        out.Clear();
        mapper.Clear();

        // 1. first go the file names of input subtitle files and its length if available
        if (!GetLine(buf, GENUSE_BUFSIZE, fConfig))
        {
            printf("! Unexpected end of file./n");
            return false;
        }

        psz = buf;
        CommonParser::SkipBlanks(psz);
        len = CommonParser::ReadAsManyDigits(psz, n);
        if (len == 0)
        {
            printf("! The number of input subtitle files unspecified./n");
            return false;
        }
        in.SetNumVols(n);
        for (int i = 0; i < n; i++)
        {
            // format:
            // abc.srt -- 00:59:28,600
            // or
            // abc.srt -- 3568600
            movtime_t    dur;
            FILE        *fIn;

            GetLine(buf, GENUSE_BUFSIZE, fConfig);
            const char *pfn = ProcessFileInfo(buf, dur);

            fIn = fopen(pfn, "r");
            if (fIn == 0)
            {
                printf("! The input file '%s' cannot be opened./n", pfn);
                return false;
            }
            else
            {
                int hr, min, sec, msec;
                Out::AnalyseTime(dur, hr, min, sec, msec);
                printf(": The input file '%s' has successfully been loaded with duration claimed to be %02d:%02d:%02d,%03d/n", pfn, hr, min, sec, msec);
            }
            
            in.AddFile(i, fIn, dur);
        }

        // 2. then come the file names of output subtitle files and its length according to the movie files if available
        if (!GetLine(buf, GENUSE_BUFSIZE, fConfig))
        {
            printf("! Unexpected end of file./n");
            return false;
        }

        psz = buf;
        CommonParser::SkipBlanks(psz);
        len = CommonParser::ReadAsManyDigits(psz, n);
        if (len == 0)
        {
            printf("! The number of output subtitle files unspecified./n");
            return false;
        }
        out.SetNumVols(n);
        for (int i = 0; i < n; i++)
        {
            // format, same as input
            movtime_t    dur;
            FILE        *fOut;

            if (!GetLine(buf, GENUSE_BUFSIZE, fConfig))
            {
                printf("! Unexpected end of file./n");
                return false;
            }
            const char *pfn = ProcessFileInfo(buf, dur);

            fOut = fopen(pfn, "w");
            if (fOut == 0)
            {
                printf("! The output file '%s' cannot be opened./n", pfn);
                return false;
            }
            else
            {
                int hr, min, sec, msec;
                Out::AnalyseTime(dur, hr, min, sec, msec);
                printf(": The output file '%s' has successfully been loaded with duration claimed to be %02d:%02d:%02d,%03d/n", pfn, hr, min, sec, msec);
            }
        
            out.AddFile(i, fOut, dur);
        }

        movtime_t st1, st2, dt1, dt2;
        // 3. here is the original subtitle temporal description
        printf(": Loading mapping from original subtitle to absolute timeaxis./n");
        while (1)
        {
            // format: time~time-->abstime~abstime
            if (!GetLine(buf, GENUSE_BUFSIZE, fConfig))
            {
                printf("! Unexpected end of file./n");
                return false;
            }
            printf("%s/n", buf);
            if (IsEmptyLine(buf))
            {
                continue;
            }
            else if (IsSepLine(buf))
            {
                break;
            }
            if (!in.parser.ParseTmapLine(buf, st1, st2, dt1, dt2))
            {
                printf("! Time syntax error./n");
                return false;
            }
            mapper.AddSubToAbs(st1, st2, dt1, dt2);
            printf(": successfully mapped %d~%d to %d~%d./n", st1, st2, dt1, dt2);
        }


        // 4. the movie temporal description
        bool noout = true;
        printf(": Loading mapping from absolute timeaxis to movie./n");
        while (1)
        {
            // format: abstime~abstime-->time~time
            if (!GetLine(buf, GENUSE_BUFSIZE, fConfig))
            {
                if (noout)
                {
                    printf("! Unexpected end of file./n");
                    return false;
                }
                else
                {
                    mapper.InitRecent();
                    return true;
                }
            }

            if (IsEmptyLine(buf))
            {
                continue;
            }

            if (!out.parser.ParseTmapLine(buf, st1, st2, dt1, dt2))
            {
                printf("! Time syntax error./n");
                return false;
            }

            mapper.AddAbsToMov(st1, st2, dt1, dt2);
            printf(": successfully mapped %d~%d to %d~%d./n", st1, st2, dt1, dt2);

            noout = false;

        }

        return false;
    }

    bool Rectify ()
    {
        Item item;
        while (in.Get(item))
        {
            out.Set(item);
        }
        return in.IsEnd();
    }
};


int main (void)
{
    FILE *fConfig = fopen("stresync_config.txt", "r");
    StResync    resync;
    if (!resync.ParseConfig(fConfig))
    {
        return 0;
    }
    if (!resync.Rectify())
    {
        return 0;
    }
    printf(": Conversion was successfully made./n");

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值