ultimatepp/uppdev/XLS/olefs.cpp
cxl b287b3d34c Testing usvn
git-svn-id: svn://ultimatepp.org/upp/trunk@1342 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2009-06-28 08:21:16 +00:00

523 lines
14 KiB
C++

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* This file is part of xlslib -- A multiplatform, C/C++ library
* for dynamic generation of Excel(TM) files.
*
* xlslib is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* xlslib 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with xlslib. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2004 Yeico S. A. de C. V.
* Copyright 2008 David Hoerl
*
* $Source: /cvsroot/xlslib/xlslib/src/oledoc/olefs.cpp,v $
* $Revision: 1.3 $
* $Author: dhoerl $
* $Date: 2008/10/25 18:39:53 $
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* File description:
*
*
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <string>
#include <XLS/ole/olefs.h>
#include <XLS/stringtok.h>
using namespace std;
using namespace xlslib_core;
/*
***********************************
COleFileSystem class Implementation
***********************************
*/
COleFileSystem::COleFileSystem()
:m_RootEntry((signed32_t)0,string("Root Entry")),
m_nProperty_Count(0)
{
m_RootEntry.SetType(PTYPE_ROOT);
m_RootEntry.SetSize(0);
m_RootEntry.SetPreviousIndex( PLINK_EMPTY);
m_RootEntry.SetNextIndex( PLINK_EMPTY);
m_RootEntry.SetChildIndex( PLINK_EMPTY);
m_RootEntry.SetStartBlock( PBLOCK_END);
m_RootEntry.SetColor(PROPERTY_COLOR_NODE_BLACK);
m_RootEntry.SetDataPointer(NULL);
m_RootEntry.SetCreatedSecs(PPT_DFLT_SECS1);
m_RootEntry.SetCreatedDays(PPT_DFLT_DAYS1);
m_RootEntry.SetModifiedSecs(PPT_DFLT_SECS2);
m_RootEntry.SetModifiedDays(PPT_DFLT_DAYS2);
}
COleFileSystem::~COleFileSystem()
{
}
/*
***********************************
***********************************
*/
int COleFileSystem::GetNode(string const &path, Tree_Level_Itor_t& node)
{
StringList_t path_list;
stringtok(path_list, path, "/");
int retval = SearchNode(&m_RootEntry, path_list, node);
// Delete dinamically created strings of path_list
// anyway the list is deleted iside SearchNode...
for (StringListItor_t pl = path_list.begin(); pl != path_list.end(); pl++)
delete *pl;
return retval;
}
/*
***********************************
***********************************
*/
int COleFileSystem::SearchNode(COleProp* base_node, StringList_t& path_list, Tree_Level_Itor_t& node_level)
{
int errcode = FS_INVALID_PATH;
if(!((base_node->m_Child_List).empty()))
{
for (StringListItor_t node_name = path_list.begin(); node_name != path_list.end(); ++node_name)
for(node_level = (base_node->m_Child_List).begin(); node_level != (base_node->m_Child_List).end(); node_level++)
{
if (**node_name == (*node_level)->GetName())
{
delete path_list.front();
path_list.pop_front(); // Remove the found element from path
if(path_list.empty()) // If it was the last element return it
{
return FS_NO_ERRORS;
}
else
{ // Recursively continue the search
return SearchNode(*node_level, path_list, node_level);
}
}
}
}
return errcode;
}
/*
***********************************
***********************************
*/
int COleFileSystem::AddDirectory(string const &dir_path)
{
int errcode = NO_ERRORS;
StringList_t path_list;
stringtok(path_list, dir_path, "/");
errcode = AddNode(&m_RootEntry, path_list);
// Delete dinamically created strings of path_list
for (StringListItor_t pl = path_list.begin(); pl != path_list.end(); pl++)
delete *pl;
if(errcode == FS_NO_ERRORS)
{
Tree_Level_Itor_t newnode;
GetNode(dir_path, newnode);
(*newnode)->SetChildIndex(PLINK_EMPTY);
(*newnode)->SetType(PTYPE_DIRECTORY);
(*newnode)->SetSize(0);
(*newnode)->SetColor(PROPERTY_COLOR_NODE_BLACK);
(*newnode)->SetDataPointer(NULL);
(*newnode)->SetCreatedSecs(PPT_DFLT_SECS1);
(*newnode)->SetCreatedDays(PPT_DFLT_DAYS1);
(*newnode)->SetModifiedSecs(PPT_DFLT_SECS2);
(*newnode)->SetModifiedDays(PPT_DFLT_DAYS2);
}
return errcode;
}
/*
***********************************
***********************************
*/
#define MIN_DATA_SIZE (0x1000)
// TODO: Change the DataStorage pass-argument
int COleFileSystem::AddFile(string const &dir_path, CDataStorage* pdata)
{
int errcode = NO_ERRORS;
StringList_t path_list;
// NOTE: Token analysis can be done inside of AddNode:
stringtok(path_list, dir_path, "/");
errcode = AddNode(&m_RootEntry, path_list);
// Delete dinamically created strings of path_list
for (StringListItor_t pl = path_list.begin(); pl != path_list.end(); pl++)
delete *pl;
if(errcode == FS_NO_ERRORS)
{
Tree_Level_Itor_t newnode;
GetNode(dir_path, newnode);
(*newnode)->SetType(PTYPE_FILE);
(*newnode)->SetChildIndex(PLINK_EMPTY);
// Calculate the trail data size needed to complete a BIG_BLOCK
unsigned32_t trail_size = (pdata->GetDataSize() % BIG_BLOCK_SIZE)?
(BIG_BLOCK_SIZE - (pdata->GetDataSize() % BIG_BLOCK_SIZE)):0;
// This library won't use Small Blocks, so all data elements shall be >0x1000
if ((trail_size + pdata->GetDataSize()) < MIN_DATA_SIZE)
{
trail_size = MIN_DATA_SIZE - pdata->GetDataSize();
(*newnode)->SetSize(MIN_DATA_SIZE);
}
else
{
// The size stored in the node is the actual size of the data (not the filled-to-bigblock one)
(*newnode)->SetSize(pdata->GetDataSize() + trail_size);
}
// create the trail data unit.
CUnit* ptraildata = new CUnit;
ptraildata->AddFixedDataArray(0x00, trail_size);
(*pdata) += ptraildata;
(*newnode)->SetDataPointer(pdata);
(*newnode)->SetColor(PROPERTY_COLOR_NODE_BLACK);
(*newnode)->SetCreatedSecs(PPT_DFLT_SECS1);
(*newnode)->SetCreatedDays(PPT_DFLT_DAYS1);
(*newnode)->SetModifiedSecs(PPT_DFLT_SECS2);
(*newnode)->SetModifiedDays(PPT_DFLT_DAYS2);
}
return errcode;
}
/*
***********************************
***********************************
*/
/*
Some special adding-node cases:
- The path to reach the node doesn't exist
- The the node already exists
*/
int COleFileSystem::AddNode(COleProp* base_node, StringList_t& path_list)
{
int errcode;
if(!(base_node->m_Child_List).empty())
{
for(Tree_Level_Itor_t node_child = (base_node->m_Child_List).begin();
node_child != (base_node->m_Child_List).end(); node_child++)
{
if((*node_child)->GetName() == **path_list.begin())
{
delete path_list.front();
path_list.pop_front(); // Remove the found element from path
return AddNode(*node_child, path_list);
}
}
}
//if the path element wasn't found, the program gets here
//... and we have two possible reasons:
// 1. The path isn't correct, so no node is created and an error msg have to be returned
// (one of the intermediate nodes is empty or doesn't exist: there are more than one path elements left)
// 2. The node is the new one we want to create.
// if the size of the path is 0, the node already existed
if(path_list.size() != 1)
{
if (path_list.size() == 0)
errcode = FS_NODE_ALREADY_EXISTS;
else
errcode = FS_INVALID_PATH;
}
else
{
unsigned8_t base_node_type = base_node->GetType();
if(base_node_type == PTYPE_DIRECTORY || base_node_type == PTYPE_ROOT)
{
#if 0
COleProp newnode(++m_nProperty_Count, *path_list.begin());
bool was_firstborn = false;
if((base_node->m_Child_List).empty()) //if this is the first child of the node...
{
base_node->SetChildIndex(m_nProperty_Count); // the new one is the child
newnode.SetPreviousIndex(PLINK_EMPTY); // there is no previous
was_firstborn = true;// mark for later
}
// The next-index of the new node shall to point to nowhere
newnode.SetNextIndex(PLINK_EMPTY);
(base_node->m_Child_List).push_back(newnode);
// Get the just added node
Tree_Level_Itor_t nodeadded = (base_node->m_Child_List).end();
nodeadded--;
// Get the previous to the just added node
Tree_Level_Itor_t prev_to_nodeadded = (base_node->m_Child_List).end();
prev_to_nodeadded--;prev_to_nodeadded--;
if(!was_firstborn)
nodeadded->SetPreviousIndex(prev_to_nodeadded->GetIndex());
// Set the next-index of the previous node to point to the newone
prev_to_nodeadded->SetNextIndex(nodeadded->GetIndex());
#else
////////////
COleProp* newnode = new COleProp(++m_nProperty_Count, **path_list.begin());
size_t childnum = (base_node->m_Child_List).size();
if(!(base_node->m_Child_List).empty()) //if this is the first child of the node...
{
Tree_Level_Itor_t lastnode = (base_node->m_Child_List).end();
lastnode--;
if(1 == childnum)
{
base_node->SetChildIndex(newnode->GetIndex()); // The 2nd child is the entry always
newnode->SetPreviousIndex((*lastnode)->GetIndex()); // The previous is the only element of the list
}
else
{
(*lastnode)->SetNextIndex(newnode->GetIndex());
newnode->SetPreviousIndex(PLINK_EMPTY); // there is no previous
}
newnode->SetNextIndex(PLINK_EMPTY); // there is no next
newnode->SetChildIndex(PLINK_EMPTY); // there is no child
}
else
{
base_node->SetChildIndex(m_nProperty_Count); // the new one is the child
newnode->SetPreviousIndex(PLINK_EMPTY); // there is no previous
newnode->SetNextIndex(PLINK_EMPTY); // there is no next
newnode->SetChildIndex(PLINK_EMPTY); // there is no child
}
(base_node->m_Child_List).push_back(newnode);
#endif
errcode = FS_NO_ERRORS;
}
else
{
errcode = FS_NODE_NOT_A_DIRECTORY;
}
}
return errcode;
}
/*
***********************************
***********************************
*/
void COleFileSystem::GetAllNodes(NodeList_t& node_list)
{
GetAllNodesList(node_list, &m_RootEntry);
SortList(node_list);
}
/*
***********************************
***********************************
*/
void COleFileSystem::GetAllNodesList(NodeList_t& node_list, COleProp* base_node)
{
if(!(base_node->m_Child_List).empty())
{
for(Tree_Level_Itor_t child_node = (base_node->m_Child_List).begin();
child_node != (base_node->m_Child_List).end(); child_node++ )
{
GetAllNodesList(node_list, (*child_node));
node_list.push_back((*child_node));
}
}
else
{
return;
}
}
/*
***********************************
An horribly inefficient sorting routine....
... until I find the way of using the list<T>::sort() function so
I can specify the sorting criteria (for this case, a member variable
of the elements of the list.
***********************************
*/
void COleFileSystem::SortList(NodeList_t& node_list)
{
NodeList_t node_list_shadow = node_list;
node_list.erase(node_list.begin(), node_list.end());
NodeList_Itor_t i;
int index = 1;
do{
for(i = node_list_shadow.begin(); i != node_list_shadow.end(); i++)
{
if((*i)->GetIndex() == index)
{
node_list.push_back(*i);
node_list_shadow.erase(i);
index++;
break;
}
}
}while(!node_list_shadow.empty());
}
/*
***********************************
***********************************
*/
unsigned32_t COleFileSystem::GetTotalDataSize()
{
NodeList_t node_list;
GetAllNodes(node_list);
unsigned32_t total_size = 0;
for(NodeList_Itor_t i = node_list.begin(); i != node_list.end(); i++)
{
if((*i)->GetType() == PTYPE_FILE)
total_size += (*i)->GetDataPointer()->GetDataSize();
}
return total_size;
}
/*
***********************************
***********************************
*/
unsigned32_t COleFileSystem::GetNumDataFiles()
{
NodeList_t node_list;
GetAllNodes(node_list);
unsigned32_t total_files = 0;
for(NodeList_Itor_t i = node_list.begin(); i != node_list.end(); i++)
{
if((*i)->GetType() == PTYPE_FILE)
total_files ++;
}
return total_files;
}
/*
***********************************
***********************************
*/
COleProp& COleFileSystem::GetRootEntry()
{
return m_RootEntry;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* $Log: olefs.cpp,v $
* Revision 1.3 2008/10/25 18:39:53 dhoerl
* 2008
*
* Revision 1.2 2004/09/01 00:47:04 darioglz
* + Modified to gain independence of target
*
* Revision 1.1.1.1 2004/08/27 16:31:43 darioglz
* Initial Import.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */