Linux thread operations

         File List

A. Second Edition
Little tools to publish all my file list as table.
B.The problem
C.The idea of program
D.The major functions

E.Further improvement
กก
F.File listing
#include <windows.h>
#include <TCHAR.h>
#include <stdio.h>


#define MY_MAX_PATH (4*MAX_PATH)

typedef bool (* HandleFileCallBack)(LPTSTR fullName, LPTSTR fileName, void* pUser);

int pathLength = 0;
int counter = 1;
DWORD numberToWrite;
DWORD number = 0;

int genericFind(LPCTSTR dir, HandleFileCallBack handleFileCallBack, LPTSTR filter=NULL, void* pUser=NULL);


LPSTR header="<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=gb2312\">\n<title>My All File List</title> \n<meta name=\"GENERATOR\" content=\"Microsoft FrontPage 6.0\"></head> \n <body><p><font color=\"#FF0000\">\n <font color=\"#FF0000\"><font size=\"7\">\nAll File List\n</font></p>\n";

LPCSTR bottom="</table> </body></html>";

LPSTR table="<table border=\"1\" cellpadding=\"5\" cellspacing=\"5\" width=\"100%\">\n<tr> <th> file index </th>  <th>\n file name \n</th>  </tr>\n";

LPSTR linkPrefix="<tr><td width=20>%d</td>\n <td> <a href=\"http://www.staroceans.net/%s\">";
LPSTR linkPosfix="</a></td></tr>";

bool createListHelper(LPTSTR fullName, LPTSTR fileName, void* pUser)
{
    char buffer[1024];   
    char linkBuffer[256];
    HANDLE hFile = (HANDLE)pUser;
    LPTSTR relativePath = fullName + pathLength;
    LPTSTR src = relativePath;
    PSTR dst = linkBuffer;
    bool bResult = false;
    int i=0;
   
   
    if (*src == _T('\\'))
    {
        //bypass the first "\\";
        src ++;
    }
    do
    {
        if (*src == _T('\\'))
        {           
            *dst = '/';
           
        }
        else
        {
            *dst = *src;
        }
        if (*src == _T('\0'))
        {
            break;
        }
        src ++;
        dst ++;
    }
    while (true);   

    sprintf(buffer, linkPrefix, counter, linkBuffer);
    numberToWrite = strlen(buffer);
    if (WriteFile(hFile, buffer, numberToWrite, &number, NULL)&& numberToWrite==number)
    {
        numberToWrite = _tcslen(fileName)*sizeof(TCHAR);
        if (WriteFile(hFile, fileName, numberToWrite, &number, NULL)&& numberToWrite==number)
        {               
            numberToWrite = strlen(linkPosfix);
            if (WriteFile(hFile, linkPosfix, numberToWrite, &number, NULL)&& numberToWrite==number)
            {
                bResult = true;
            }
        }
    }
    counter ++;
   
    return bResult;
}
   

void createList(LPTSTR path, LPTSTR fileName)
{
    HANDLE hFile = INVALID_HANDLE_VALUE;
    if ((hFile = CreateFile(fileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL))!= INVALID_HANDLE_VALUE)
    {       
        numberToWrite = strlen(header);
        pathLength = _tcslen(path);
        if (WriteFile(hFile, header, numberToWrite, &number, NULL) && number == numberToWrite)
        {   
            numberToWrite = strlen(table);
            if (WriteFile(hFile, table, numberToWrite, &number, NULL) && number == numberToWrite)
            {   
                genericFind(path, createListHelper, NULL, hFile);
            }
        }
        numberToWrite =strlen(bottom);

        WriteFile(hFile, bottom, numberToWrite, &number, NULL);
   
        CloseHandle(hFile);
    }
}


int genericFind(LPCTSTR dir, HandleFileCallBack handleFileCallBack, LPTSTR filter, void* pUser)
{
    HANDLE handle;
    int nCounter = 0;
    TCHAR curFileName[MY_MAX_PATH];
    TCHAR wildFileName[MY_MAX_PATH];
    LPTSTR strFileName;
   
    WIN32_FIND_DATA ffd;

    if (filter == NULL)
    {
        strFileName = _T("*.*");
    }
    else
    {
        strFileName = filter;
    }


    _sntprintf(wildFileName, MY_MAX_PATH, _T("%s\\%s"), dir, strFileName);
    handle = FindFirstFile(wildFileName, &ffd);
    if (handle==INVALID_HANDLE_VALUE)
    {
        _tprintf(_T("findfirst failed of error code =%d\n"), GetLastError());
        return 0;
    }
    do
    {   
        if (_tcsicmp(ffd.cFileName, _T("."))!=0 && _tcsicmp(ffd.cFileName, _T(".."))!=0)
        {
            _stprintf(curFileName, _T("%s\\%s"), dir, ffd.cFileName);
            if  (GetFileAttributes(curFileName)&FILE_ATTRIBUTE_DIRECTORY)
            {
                // filter my personal folder
                if (_tcsicmp(ffd.cFileName, _T("personal")) !=0)
                {
                    genericFind(curFileName, handleFileCallBack, filter, pUser);
                }
            }
            else
            {                   
                if (!handleFileCallBack(curFileName, ffd.cFileName, pUser))
                {
                    break;
                }
                else
                {
                    nCounter ++;
                }
            }
        }
    }
    while (FindNextFile(handle, &ffd));   
   
    FindClose(handle);
    return nCounter;
}



int _tmain(int argc, LPTSTR* argv)
{
    //I:\MyWeb\diabloforum mylist.htm
    if (argc == 3)
    {   
        createList(argv[1], argv[2]);
    }
    return 0;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// This is the latest version by using boost as there are some nasty thing about language encoding problem with windows
// api. It is said, in windows, you should always use wide-char api and widestring, but in linux, you should almost never
// use wide char. Till now, I don't really understand this but it works.

#include <iostream>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <string>
#include <map>
#include <algorithm>
#include <cstdio>

using namespace std;
using namespace boost::filesystem;

typedef multimap<string, string> StringMap;

string prefix = "http://www.staroceans.net";

string header1="<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"><title>My All File List</title>";
string header2="<meta name=\"GENERATOR\" content=\"Microsoft FrontPage 6.0\"></head>  <body><p><font color=\"#FF0000\">";
string header3="<font color=\"#FF0000\"><font size=\"7\">All File List</font></p>";

string comment1="This is a list of all files in this website and to make it easy for searching, the they are sorted by file name"
    " and here is <a href=\"";
string comment2="/myListTool.html\"> the source code </a> of file how it is generated.";

string tableHeader1="<table border=\"1\" cellpadding=\"5\" cellspacing=\"5\" width=\"100%\">";
string tableHeader2="<tr> <th> file index </th>  <th> file name </th>   </tr>";
string bottom="</table></body></html>";

string tableColumn1 = "<tr> <td width=20>";
string tableColumn2 = "</td>  <td> <a href=\"";
string tableColumn3 = "\">";
string tableColumn4 = "</a> </td> </tr>";



string urlEncode(const string& str)
{
    string result;
    for (int i = 0; i < str.size(); i ++)
    {
        if (str[i]>='0' && str[i] <='9' || str[i]>='A' && str[i] <='Z' || str[i] >= 'a' && str[i] <= 'z')
        {
            result+= str[i];
        }
        else
        {
            const unsigned char MASK1 = 0xF0;
            const unsigned char MASK2 = 0x0F;
            unsigned char ch;

            switch (str[i])
            {
            case '-':
            case '_':
            case '.':
            case '!':
            case '~':
            case '*':
            case '\'':
            case '(':
            case ')':
            case '"':
                result += str[i];
                break;
            default:
                ch = (str[i] & MASK1) >> 4;
                result += '%';

                if (ch > 9)
                {
                    ch = ch - 10 + 'A';
                }
                else
                {
                    ch = ch + '0';
                }
                result += ch;
                ch = str[i] & MASK2;
                if (ch > 9)
                {
                    ch = ch - 10 + 'A';
                }
                else
                {
                    ch = ch + '0';
                }
                result += ch;
                break;
            }
        }
    }
    return result;
}


void doFile(const string& filePath, StringMap& stringMap, const string& prefix)
{
    //cout<<filePath.file_string()<<endl;
    //cout<<filePath.filename()<<endl;
    string str = prefix + "/" + urlEncode(filePath);

    if (stringMap.insert(make_pair<string, string>(filePath, str)) == stringMap.end())
    {
        //cout<<"error"<<endl;
    }
}

void doDir(const path& thePath, StringMap& stringMap, const string& prefix)
{
    directory_iterator it(thePath), dirEnd;
    while (it != dirEnd)
    {
        //cout<< it->filename()<<endl;
        if (is_directory(*it))
        {
            //cout<< it->filename()<<endl;
            // check if it has white space in between.
            string subPrefix = prefix + "/" + urlEncode(it->filename());
            if (it->filename().compare("personal") != 0)
            {
                doDir(*it, stringMap, subPrefix);
            }
        }
        else
        {
            if (is_regular_file(*it))
            {
                //string str = urlEncode(it->filename());
                doFile(it->filename(), stringMap, prefix);
            }
            else
            {
                //cout<<"file is not regular:"<<it->filename()<<endl;
            }
        }
        it ++;
    }


}

struct ShowStringPair
{
    void showString(const string& str) const
    {
        for (int i = 0; i < str.size(); i ++)
        {
            unsigned char ch = str[i];
            cout<<ch;
            cout.flush();
        }
    }

    void operator()(const pair<string, string>& strPair) const
    {
        //cout<<"key:";
        showString(strPair.first);
        cout<<"; value:";
        showString(strPair.second);
        cout<<endl;
        //cout <<tableColumn1<<total<<tableColumn2<<str<<tableColumn3<<subDir<<tableColumn4<<endl;
    }
};

void showString(const string& str)
{
    for (int i = 0; i < str.size(); i ++)
    {
        unsigned char ch = str[i];
        cout<<ch;
        //cout.flush();
    }
}

void showMap(const StringMap& stringMap)
{
    cout<<header1<<header2<<header3<<endl;
    cout<<tableHeader1<<tableHeader2<<endl;
    cout<<comment1<<prefix<<comment2<<endl;
    int counter = 1;
    for (StringMap::const_iterator it =  stringMap.begin(); it != stringMap.end(); it ++)
    {
        cout << tableColumn1 << counter << tableColumn2;
        showString(it->second);
        cout << tableColumn3;
        showString(it->first);
        cout << tableColumn4;
        counter ++;
    }
    cout<< bottom<<endl;
}



int main()
{
    path srcPath("/media/unused/diabloforum");
    //path srcPath("/media/unused/diabloforum/DC/HWBooks/Serial Communications Dev guide");
    //path srcPath("/media/unused/USB Design By Example");

    //path dstPath = srcPath.parent_path() / "dst";
    StringMap stringMap;

    doDir(srcPath, stringMap, prefix);

    //for_each(stringMap.begin(), stringMap.end(), ShowStringPair());
    showMap(stringMap);
    return 0;
}








/*
void copy_directory(const path& src, const path& dst)
{
    if (is_directory(src) && is_directory(dst))
    {
        directory_iterator srcIt(src), itEnd;
        while (srcIt != itEnd)
        {
            path dstPath = dst / srcIt->filename();
            //cout<<"src="<<srcIt->filename() <<endl<<"dst="<<dstPath->filename()<<endl;

            if (is_regular_file(*srcIt))
            {
                copy_file(*srcIt, dstPath);
            }
            else
            {
                if (is_directory(*srcIt))
                {
                    create_directory(dstPath);
                    copy_directory(*srcIt, dstPath);
                }
            }
            srcIt ++;
        }
    }
}


int main()
{
    path srcPath("/home/nick/myprojects/mytest");
    path dstPath = srcPath.parent_path() / "dst";
    cout<<srcPath.filename().c_str()<<endl;

    //doDir(srcPath);
    if (! exists(dstPath))
    {
        create_directory(dstPath);
    }

    if (is_directory(dstPath))
    {
        copy_directory(srcPath, dstPath);
    }

    //copy_directory(srcPath, dstPath);
    return 0;
}
*/
///////////////////////////////////////////////////////////////////////////////////
// made some trivial changes...
/*
 * myListTool.cpp
 *
 *  Created on: Feb 23, 2013
 *      Author: nick
 */


// This is the latest version by using boost as there are some nasty thing about language encoding problem with windows
// api. It is said, in windows, you should always use wide-char api and widestring, but in linux, you should almost never
// use wide char. Till now, I don't really understand this but it works.

#include <iostream>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <string>
#include <map>
#include <algorithm>
#include <cstdio>

using namespace std;
using namespace boost::filesystem;

typedef multimap<string, string> StringMap;

string prefix = "http://www.staroceans.net";

string header1="<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"><title>My All File List</title>";
string header2="<meta name=\"GENERATOR\" content=\"Microsoft FrontPage 6.0\"></head>  <body><p><font color=\"#FF0000\">";
string header3="<font color=\"#FF0000\"><font size=\"7\">All File List</font></p>";

string comment1="This is a list of all files in this website and to make it easy for searching, the they are sorted by file name"
    " and here is <a href=\"";
string comment2="/myListTool.html\"> the source code </a> of file how it is generated.";

string tableHeader1="<table border=\"1\" cellpadding=\"5\" cellspacing=\"5\" width=\"100%\" table-layout=\"fixed\""
        "   <colgroup>"
       "<col span=\"1\" style=\"width: 15%;\">"
       "<col span=\"1\" style=\"width: 70%;\">"
       "<col span=\"1\" style=\"width: 15%;\">"
    "</colgroup>>";
string tableHeader2="<tr> <th> file index </th>  <th> file name </th>  <th> file path </th> </tr>";
string bottom="</table></body></html>";

string tableColumn1 = "<tr> <td style=\"width: 5%;\">";
string tableColumn2 = "</td>  <td style=\"width: 20%;\" > <a href=\"";
string tableColumn3 = "\">";
string tableColumn4 = "</a> </td> <td style=\"width: 75%;\">";
string tableColumn5 = "</td></tr>";



string urlEncode(const string& str)
{
    string result;
    for (int i = 0; i < str.size(); i ++)
    {
        if (str[i]>='0' && str[i] <='9' || str[i]>='A' && str[i] <='Z' || str[i] >= 'a' && str[i] <= 'z')
        {
            result+= str[i];
        }
        else
        {
            const unsigned char MASK1 = 0xF0;
            const unsigned char MASK2 = 0x0F;
            unsigned char ch;

            switch (str[i])
            {
            case '-':
            case '_':
            case '.':
            case '!':
            case '~':
            case '*':
            case '\'':
            case '(':
            case ')':
            case '"':
                result += str[i];
                break;
            default:
                ch = (str[i] & MASK1) >> 4;
                result += '%';

                if (ch > 9)
                {
                    ch = ch - 10 + 'A';
                }
                else
                {
                    ch = ch + '0';
                }
                result += ch;
                ch = str[i] & MASK2;
                if (ch > 9)
                {
                    ch = ch - 10 + 'A';
                }
                else
                {
                    ch = ch + '0';
                }
                result += ch;
                break;
            }
        }
    }
    return result;
}


void doFile(const string& fileName, StringMap& stringMap, const string& prefix, const string& filePath)
{
    //cout<<filePath.file_string()<<endl;
    //cout<<filePath.filename()<<endl;
    string str = prefix + "/" + urlEncode(fileName);

    if (stringMap.insert(make_pair<string, string>(filePath+"/"+fileName, str)) == stringMap.end())
    {
        //cout<<"error"<<endl;
    }
}

void doDir(const path& thePath, StringMap& stringMap, const string& prefix, const string& filePath)
{
    directory_iterator it(thePath), dirEnd;
    while (it != dirEnd)
    {
        //cout<< it->filename()<<endl;
        if (is_directory(*it))
        {
            //cout<< it->filename()<<endl;
            // check if it has white space in between.
            string subPrefix = prefix + "/" + urlEncode(it->filename());
            string subFilePath = filePath + "/" + it->filename();
            if (it->filename().compare("personal") != 0 && it->filename()[0] != '.')
            {
                doDir(*it, stringMap, subPrefix, subFilePath);
            }
        }
        else
        {
            if (is_regular_file(*it))
            {
                //string str = urlEncode(it->filename());
                // bypass hiden files
                if (it->filename()[0] != '.')
                {
                    doFile(it->filename(), stringMap, prefix, filePath);
                }
            }
            else
            {
                //cout<<"file is not regular:"<<it->filename()<<endl;
            }
        }
        it ++;
    }


}

struct ShowStringPair
{
    void showString(const string& str) const
    {
        for (unsigned int i = 0; i < str.size(); i ++)
        {
            unsigned char ch = str[i];
            cout<<ch;
            cout.flush();
        }
    }

    void operator()(const pair<string, string>& strPair) const
    {
        //cout<<"key:";
        showString(strPair.first);
        cout<<"; value:";
        showString(strPair.second);
        cout<<endl;
        //cout <<tableColumn1<<total<<tableColumn2<<str<<tableColumn3<<subDir<<tableColumn4<<endl;
    }
};

void showString(const string& str)
{
    for (int i = 0; i < str.size(); i ++)
    {
        unsigned char ch = str[i];
        cout<<ch;
        //cout.flush();
    }
}

void showMap(const StringMap& stringMap)
{
    cout<<header1<<header2<<header3<<endl;
    cout<<tableHeader1<<tableHeader2<<endl;
    cout<<comment1<<prefix<<comment2<<endl;
    int counter = 1;
    for (StringMap::const_iterator it =  stringMap.begin(); it != stringMap.end(); it ++)
    {
        size_t pos = it->first.find_last_of('/');
        cout << tableColumn1 << counter << tableColumn2;
        showString(it->second);
        cout << tableColumn3;
        showString(it->first.substr(pos+1));
        cout << tableColumn4;

        cout <<  it->first;
        cout << tableColumn5;
        counter ++;
    }
    cout<< bottom<<endl;
}



int main()
{
    path srcPath("/media/FLASH32G/MyWeb/diabloforum");
    //path srcPath("/media/unused/diabloforum/DC/HWBooks/Serial Communications Dev guide");
    //path srcPath("/media/unused/USB Design By Example");

    //path dstPath = srcPath.parent_path() / "dst";
    StringMap stringMap;

    doDir(srcPath, stringMap, prefix, "");

    //for_each(stringMap.begin(), stringMap.end(), ShowStringPair());
    showMap(stringMap);
    return 0;
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/****************************************************************************************************************************************/
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/****************************************************************************************************************************************/
// Add file size to file path...
/*
 * myListTool.cpp
 *
 *  Created on: Sep 1, 2013
 *      Author: nick
 *    Boost is really a headache as the version is keep upgrading and the interace is
 *    changed constantly according to developer's personal favorite.
 *    This is compiled under boost1.46
 */

// This is the latest version by using boost as there are some nasty thing about language encoding problem with windows
// api. It is said, in windows, you should always use wide-char api and widestring, but in linux, you should almost never
// use wide char. Till now, I don't really understand this but it works.
#include <iostream>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <string>
#include <map>
#include <algorithm>
#include <cstdio>

using namespace std;
using namespace boost::filesystem;

typedef multimap<string, string> StringMap;

string prefix = "http://www.staroceans.net";

string header1 =
        "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"><title>My All File List</title>";
string header2 =
        "<meta name=\"GENERATOR\" content=\"Microsoft FrontPage 6.0\"></head>  <body><p><font color=\"#FF0000\">";
string header3 =
        "<font color=\"#FF0000\"><font size=\"7\">All File List</font></p>";

string comment1 =
        "This is a list of all files in this website and to make it easy for searching, the they are sorted by file name"
                " and here is <a href=\"";
string comment2 =
        "/myListTool.html\"> the source code </a> of file how it is generated.";

string tableHeader1 =
        "<table border=\"1\" cellpadding=\"5\" cellspacing=\"5\" width=\"100%\" table-layout=\"fixed\""
                "   <colgroup>"
                "<col span=\"1\" style=\"width: 15%;\">"
                "<col span=\"1\" style=\"width: 70%;\">"
                "<col span=\"1\" style=\"width: 15%;\">"
                "</colgroup>>";
string tableHeader2 =
        "<tr> <th> file index </th>  <th> file name </th>  <th> file path </th> </tr>";
string bottom = "</table></body></html>";

string tableColumn1 = "<tr> <td style=\"width: 5%;\">";
string tableColumn2 = "</td>  <td style=\"width: 20%;\" > <a href=\"";
string tableColumn3 = "\">";
string tableColumn4 = "</a> </td> <td style=\"width: 75%;\">";
string tableColumn5 = "</td></tr>";

string urlEncode(const string& str)
{
    string result;
    for (size_t i = 0; i < str.size(); i++)
    {
        if ((str[i] >= '0' && str[i] <= '9') || (str[i] >= 'A' && str[i] <= 'Z')
                || (str[i] >= 'a' && str[i] <= 'z'))
        {
            result += str[i];
        }
        else
        {
            const unsigned char MASK1 = 0xF0;
            const unsigned char MASK2 = 0x0F;
            unsigned char ch;

            switch (str[i])
            {
            case '-':
            case '_':
            case '.':
            case '!':
            case '~':
            case '*':
            case '\'':
            case '(':
            case ')':
            case '"':
                result += str[i];
                break;
            default:
                ch = (str[i] & MASK1) >> 4;
                result += '%';

                if (ch > 9)
                {
                    ch = ch - 10 + 'A';
                }
                else
                {
                    ch = ch + '0';
                }
                result += ch;
                ch = str[i] & MASK2;
                if (ch > 9)
                {
                    ch = ch - 10 + 'A';
                }
                else
                {
                    ch = ch + '0';
                }
                result += ch;
                break;
            }
        }
    }
    return result;
}

void doFile(const string& fileName, StringMap& stringMap, const string& prefix,
        const string& filePath, const string& fileSizeStr)
{
    //cout<< "dofile: " << filePath.string()<<endl;
    //cout<<filePath.filename()<<endl;
    string str = prefix + "/" + urlEncode(fileName);

    if (stringMap.insert(
            make_pair<string, string>(filePath + "/" + fileName + fileSizeStr,
                    str)) == stringMap.end())
    {
        //cout<<"error"<<endl;
    }
}

string getFileSizeStr(const path& p)
{
    char buf[64];
    uintmax_t size = file_size(p);
    char unit_str = 'B';
    if (size >= 1024)
    {
        // in k
        size = size / 1024;
        unit_str = 'K';
        if (size >= 1024)
        {
            // in M
            size = size / 1024;
            unit_str = 'M';
            if (size >= 1024)
            {
                // in G
                size = size / 1024;
                unit_str = 'G';
            }
        }
    }
    sprintf(buf, "[%lu%c]", (unsigned long) size, unit_str);
    //printf("filename=%s has size of %s\n", p.filename().c_str(), buf);
    return string(buf);
}

void doDir(const path& thePath, StringMap& stringMap, const string& prefix,
        const string& filePath)
{
    directory_iterator it(thePath), dirEnd;
    while (it != dirEnd)
    {
        const string str = it->path().filename().string();
        if (is_symlink(it->symlink_status()))
        {
            //cout << "symlink: " << str << endl;
        }
        else
        {
            //cout<< it->filename()<<endl;
            if (is_directory(*it))
            {
                //cout<< "dir: " << str<<endl;
                // check if it has white space in between.
                //string str = it->path().string();
                string subPrefix = prefix + "/" + urlEncode(str);
                string subFilePath = filePath + "/" + str;
                if (str.compare("personal") != 0 && str[0] != '.')
                {
                    doDir(*it, stringMap, subPrefix, subFilePath);
                }
            }
            else
            {
                if (is_regular_file(*it))
                {
                    //string str = urlEncode(it->filename());
                    // bypass hiden files
                    //cout << "file: " << str << endl;
                    if (str[0] != '.')
                    {
                        string fileSizeStr = getFileSizeStr(*it);
                        doFile(str, stringMap, prefix, filePath, fileSizeStr);
                    }
                }
                else
                {
                    //cout<<"file is not regular:"<< str <<endl;
                }
            }
        }
        it++;
    }

}

struct ShowStringPair
{
    void showString(const string& str) const
    {
        for (unsigned int i = 0; i < str.size(); i++)
        {
            unsigned char ch = str[i];
            cout << ch;
            cout.flush();
        }
    }

    void operator()(const pair<string, string>& strPair) const
    {
        //cout<<"key:";
        showString(strPair.first);
        cout << "; value:";
        showString(strPair.second);
        cout << endl;
        //cout <<tableColumn1<<total<<tableColumn2<<str<<tableColumn3<<subDir<<tableColumn4<<endl;
    }
};

void showString(const string& str)
{
    for (size_t i = 0; i < str.size(); i++)
    {
        unsigned char ch = str[i];
        cout << ch;
        //cout.flush();
    }
}

void showMap(const StringMap& stringMap)
{
    cout << header1 << header2 << header3 << endl;
    cout << tableHeader1 << tableHeader2 << endl;
    cout << comment1 << prefix << comment2 << endl;
    int counter = 1;
    for (StringMap::const_iterator it = stringMap.begin();
            it != stringMap.end(); it++)
    {
        size_t pos = it->first.find_last_of('/');
        cout << tableColumn1 << counter << tableColumn2;
        showString(it->second);
        cout << tableColumn3;
        string str = it->first.substr(pos + 1);
        pos = str.find_last_of('[');
        showString(str.substr(0, pos));
        cout << tableColumn4;

        cout << it->first;
        cout << tableColumn5;
        counter++;
    }
    cout << bottom << endl;
}

int main()
{
    path srcPath("/mnt/BigDisk/nick/Downloads/FLASH32G/MyWeb/diabloforum");
    //path srcPath("/media/unused/diabloforum/DC/HWBooks/Serial Communications Dev guide");
    //path srcPath("/media/unused/USB Design By Example");

    //path dstPath = srcPath.parent_path() / "dst";
    StringMap stringMap;

    doDir(srcPath, stringMap, prefix, "");

    //for_each(stringMap.begin(), stringMap.end(), ShowStringPair());
    showMap(stringMap);
    return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////
// I don't like boost any more, using linux api to make life easier.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/****************************************************************************************************************************************/
// Add file size to file path...
/*
 * myListTool.cpp
 *
 *  Created on: Sep 1, 2013
 *      Author: nick
 *    Boost is really a headache as the version is keep upgrading and the interace is
 *    changed constantly according to developer's personal favorite.
 *    This is compiled under boost1.46
 */

// This is the latest version by using boost as there are some nasty thing about language encoding problem with windows
// api. It is said, in windows, you should always use wide-char api and widestring, but in linux, you should almost never
// use wide char. Till now, I don't really understand this but it works.
#include <iostream>
#include <string>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>


using namespace std;


typedef multimap<string, string> StringMap;

string prefix = "http://www.staroceans.org";

string header1 =
        "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"><title>My All File List</title>";
string header2 =
        "<meta name=\"GENERATOR\" content=\"Microsoft FrontPage 6.0\"></head>  <body><p><font color=\"#FF0000\">";
string header3 =
        "<font color=\"#FF0000\"><font size=\"7\">All File List</font></p>";

string comment1 =
        "This is a list of all files in this website and to make it easy for searching, the they are sorted by file name"
                " and here is <a href=\"";
string comment2 =
        "/myListTool.html\"> the source code </a> of file how it is generated.";

string tableHeader1 =
        "<table border=\"1\" cellpadding=\"5\" cellspacing=\"5\" width=\"100%\" table-layout=\"fixed\""
                "   <colgroup>"
                "<col span=\"1\" style=\"width: 15%;\">"
                "<col span=\"1\" style=\"width: 70%;\">"
                "<col span=\"1\" style=\"width: 15%;\">"
                "</colgroup>>";
string tableHeader2 =
        "<tr> <th> file index </th>  <th> file name </th>  <th> file path </th> </tr>";
string bottom = "</table></body></html>";

string tableColumn1 = "<tr> <td style=\"width: 5%;\">";
string tableColumn2 = "</td>  <td style=\"width: 20%;\" > <a href=\"";
string tableColumn3 = "\">";
string tableColumn4 = "</a> </td> <td style=\"width: 75%;\">";
string tableColumn5 = "</td></tr>";

string urlEncode(const string& str)
{
    string result;
    for (size_t i = 0; i < str.size(); i++)
    {
        if ((str[i] >= '0' && str[i] <= '9') || (str[i] >= 'A' && str[i] <= 'Z')
                || (str[i] >= 'a' && str[i] <= 'z'))
        {
            result += str[i];
        }
        else
        {
            const unsigned char MASK1 = 0xF0;
            const unsigned char MASK2 = 0x0F;
            unsigned char ch;

            switch (str[i])
            {
            case '-':
            case '_':
            case '.':
            case '!':
            case '~':
            case '*':
            case '\'':
            case '(':
            case ')':
            case '"':
                result += str[i];
                break;
            default:
                ch = (str[i] & MASK1) >> 4;
                result += '%';

                if (ch > 9)
                {
                    ch = ch - 10 + 'A';
                }
                else
                {
                    ch = ch + '0';
                }
                result += ch;
                ch = str[i] & MASK2;
                if (ch > 9)
                {
                    ch = ch - 10 + 'A';
                }
                else
                {
                    ch = ch + '0';
                }
                result += ch;
                break;
            }
        }
    }
    return result;
}

void doFile(const string& strFileName, StringMap& stringMap, const string& strUrl, const string& strRelativePath, const string& strFileSizeStr)
{
    //cout<< "dofile: " << filePath.string()<<endl;
    //cout<<filePath.filename()<<endl;

    if (stringMap.insert(
            make_pair<string, string>(strRelativePath + strFileSizeStr,
                    strUrl)) == stringMap.end())
    {
        //cout<<"error"<<endl;
    }
}

string getFileSizeStr(size_t size)
{
    char buf[64];

    char unit_str = 'B';
    if (size >= 1024)
    {
        // in k
        size = size / 1024;
        unit_str = 'K';
        if (size >= 1024)
        {
            // in M
            size = size / 1024;
            unit_str = 'M';
            if (size >= 1024)
            {
                // in G
                size = size / 1024;
                unit_str = 'G';
            }
        }
    }
    sprintf(buf, "[%lu%c]", (unsigned long) size, unit_str);
    //printf("filename=%s has size of %s\n", p.filename().c_str(), buf);
    return string(buf);
}

size_t getFileSize(const string& subFilePath)
{
    struct stat st;
    size_t size = 0;
    if (stat(subFilePath.c_str(), &st) == 0)
    {
        size = st.st_size;
    }
    return size;
}

void doDir(const string& strRootPath,  const string& strUrl, const string& strRelativePath, StringMap& stringMap)
{
    string strPath = strRootPath + "/" + strRelativePath;
    DIR* pDir = opendir(strPath.c_str());
    if (pDir)
    {
        struct dirent* pEnt;
        while ((pEnt = readdir(pDir))!= NULL)
        {
            string strFileName = pEnt->d_name;
            string strSubPath = strPath + "/" + strFileName;
            string strSubUrl = strUrl + "/" + urlEncode(strFileName);
            string strSubRelativePath = strRelativePath + "/" + strFileName;
            switch (pEnt->d_type)
            {
            case DT_REG:
                // I don't want to add hidden files now...
                if (strFileName[0] != '.')
                {
                    size_t size = getFileSize(strSubPath);
                    string strFileSizeStr = getFileSizeStr(size);
                    doFile(strFileName, stringMap, strSubUrl, strSubRelativePath, strFileSizeStr);
                }
                break;
            case DT_DIR:
                if (strFileName.compare("personal") != 0 && strFileName[0] != '.')
                {
                    doDir(strRootPath, strSubUrl, strSubRelativePath, stringMap);
                }
                break;
            default:
                cout<<"file is not regular:"<< strFileName <<endl;
                break;
            }
        }
        closedir(pDir);
    }
}

struct ShowStringPair
{
    void showString(const string& str) const
    {
        for (unsigned int i = 0; i < str.size(); i++)
        {
            unsigned char ch = str[i];
            cout << ch;
            cout.flush();
        }
    }

    void operator()(const pair<string, string>& strPair) const
    {
        //cout<<"key:";
        showString(strPair.first);
        cout << "; value:";
        showString(strPair.second);
        cout << endl;
        //cout <<tableColumn1<<total<<tableColumn2<<str<<tableColumn3<<subDir<<tableColumn4<<endl;
    }
};

void showString(const string& str)
{
    for (size_t i = 0; i < str.size(); i++)
    {
        unsigned char ch = str[i];
        cout << ch;
        //cout.flush();
    }
}

void showMap(const StringMap& stringMap)
{
    cout << header1 << header2 << header3 << endl;
    cout << tableHeader1 << tableHeader2 << endl;
    cout << comment1 << prefix << comment2 << endl;
    int counter = 1;
    for (StringMap::const_iterator it = stringMap.begin();
            it != stringMap.end(); it++)
    {
        size_t pos = it->first.find_last_of('/');
        cout << tableColumn1 << counter << tableColumn2;
        showString(it->second);
        cout << tableColumn3;
        string str = it->first.substr(pos + 1);
        pos = str.find_last_of('[');
        showString(str.substr(0, pos));
        cout << tableColumn4;

        cout << it->first;
        cout << tableColumn5;
        counter++;
    }
    cout << bottom << endl;
}

int main()
{
    string srcPath("/home/nick/diabloforum");

    //path dstPath = srcPath.parent_path() / "dst";
    StringMap stringMap;

    doDir(srcPath, prefix, "", stringMap);

    //for_each(stringMap.begin(), stringMap.end(), ShowStringPair());
    showMap(stringMap);
    return 0;
}











                                 back.gif (341 bytes)       up.gif (335 bytes)         next.gif (337 bytes)