Commit f327bb0c authored by Laurent Claustre's avatar Laurent Claustre

backport to c++ 89 OrderedMap added in master branch for fixing CBF saving format issue

parent cf520fca
//###########################################################################
// This file is part of LImA, a Library for Image Acquisition
//
// Copyright (C) : 2009-2019
// European Synchrotron Radiation Facility
// CS40220 38043 Grenoble Cedex 9
// FRANCE
//
// Contact: lima@esrf.fr
//
// This is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This software 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, see <http://www.gnu.org/licenses/>.
//###########################################################################
#ifndef ORDEREDMAP_H
#define ORDEREDMAP_H
#include <vector>
#include <map>
#include <algorithm>
#include <stdexcept>
namespace lima {
template <class Key>
class OrderedMapComp
{
public:
typedef std::vector<Key> List;
OrderedMapComp(List& l) : m_list(l)
{}
OrderedMapComp& operator =(const OrderedMapComp&)
{
return *this;
}
bool operator()(const Key& a, const Key& b) const
{
const typename List::const_iterator f = m_list.begin();
const typename List::const_iterator l = m_list.end();
const typename List::const_iterator ia = std::find(f, l, a);
const typename List::const_iterator ib = std::find(f, l, b);
if ((ia == l) && (ib == l))
return std::less<Key>()(a, b);
return ((ia != l) && ((ib == l) || (ia < ib)));
}
private:
std::vector<Key>& m_list;
};
template <class Key, class T>
class OrderedMap
{
public:
typedef OrderedMapComp<Key> Comp;
typedef std::map<Key, T, Comp> Map;
OrderedMap() : m_comp(m_list), m_map(m_comp)
{}
OrderedMap(const OrderedMap& other)
: m_list(other.m_list), m_comp(m_list), m_map(m_comp)
{
m_map = other.m_map;
}
// OrderedMap(std::initializer_list<Map::value_type> init)
// : m_comp(m_list), m_map(m_comp)
// {
// typedef std::initializer_list<Map::val> > InitList;
// InitList::const_iterator it, l = init.end();
// for (it = init.begin(); it != l; ++it)
// insert(*it);
// }
typename Map::iterator begin()
{ return m_map.begin(); }
typename Map::const_iterator begin() const
{ return m_map.begin(); }
typename Map::iterator end()
{ return m_map.end(); }
typename Map::const_iterator end() const
{ return m_map.end(); }
bool empty() const
{ return m_map.empty(); }
T& operator [](const Key& key)
{
_checkKey(key);
return m_map[key];
}
void clear()
{
m_map.clear();
m_list.clear();
}
std::pair<typename Map::iterator, bool> insert(const typename Map::value_type& value)
{
_checkKey(value.first);
return m_map.insert(value);
}
template<class InputIt>
void insert(InputIt first, InputIt last)
{
while (first != last)
insert(*first++);
}
typename Map::iterator find(const Key& key)
{
return m_map.find(key);
}
typename Map::const_iterator find(const Key& key) const
{
return m_map.find(key);
}
typename Map::iterator erase(typename Map::const_iterator pos)
{
Key key = pos->first;
typename Map::iterator it = m_map.erase(pos);
_eraseKey(key);
return it;
}
// iterator erase(const_iterator first, const_iterator last);
// void swap(OrderedMap& other);
OrderedMap& operator =(const OrderedMap& other)
{
clear();
m_list = other.m_list;
m_map = other.m_map;
return *this;
}
private:
void _checkKey(const Key& key)
{
const typename std::vector<Key>::const_iterator f = m_list.begin();
const typename std::vector<Key>::const_iterator l = m_list.end();
if (std::find(f, l, key) == l)
m_list.push_back(key);
}
std::vector<Key> _eraseKey(const Key& key)
{
const typename std::vector<Key>::const_iterator f = m_list.begin();
const typename std::vector<Key>::const_iterator l = m_list.end();
const typename std::vector<Key>::const_iterator it = std::find(f, l, key);
if (it == l)
throw std::out_of_range("Error erasing OrderedMap key");
return m_list.erase(it);
}
std::vector<Key> m_list;
OrderedMapComp<Key> m_comp;
Map m_map;
};
} // namespace lima
#endif // ORDEREDMAP_H
......@@ -34,6 +34,7 @@
#include "lima/CtControl.h"
#include "lima/CtConfig.h"
#include "lima/HwSavingCtrlObj.h"
#include "lima/OrderedMap.h"
struct Data;
class TaskEventCallback;
......@@ -113,7 +114,8 @@ namespace lima {
};
typedef std::pair<std::string, std::string> HeaderValue;
typedef std::map<std::string,std::string> HeaderMap;
typedef std::map<std::string, std::string> HeaderMap;
typedef OrderedMap<std::string, std::string> HeaderOrderedMap;
typedef std::map<long,Data> FrameMap;
// --- file parameters
......
......@@ -74,7 +74,9 @@ class SaveContainerCbf::Compression : public SinkTaskBase
int _fillHeader(Data &aData,CtSaving::HeaderMap &aHeader,cbf_handle cbf)
{
DEB_MEMBER_FUNCT();
CtSaving::HeaderOrderedMap anOrderedHeader;
cbf_failnez(cbf_new_datablock(cbf, "image_0"));
aData.header.lock();
......@@ -82,6 +84,35 @@ class SaveContainerCbf::Compression : public SinkTaskBase
aHeader.insert(aDataHeader.begin(),aDataHeader.end());
aData.header.unlock();
// Here prepare a Ordered HeaderMap, so sort the header values and insert them
// according to some conventions like Dectris Mini CBF:
// Dectris Mini CBF, look for categories
// 'array_data/header_convention' and 'array_data/header_contents',
// they must be inserted in the header in special order,
// 'convention' BEFORE 'contents'
CtSaving::HeaderMap::iterator it1, it2;
it1 = aHeader.find("array_data/header_convention");
if (it1 != aHeader.end())
{
it2 = aHeader.find("array_data/header_contents");
if (it2 != aHeader.end())
{
anOrderedHeader.insert(*it1);
anOrderedHeader.insert(*it2);
aHeader.erase(it1);
aHeader.erase(it2);
}
}
_fillHeaderFromMap<CtSaving::HeaderMap>(aHeader, cbf);
// Now append ordered header if any
_fillHeaderFromMap<CtSaving::HeaderOrderedMap>(anOrderedHeader, cbf);
return 0;
}
template <class T>
int _fillHeaderFromMap(T& aHeader, cbf_handle cbf)
{
std::string previousCategory;
for(CtSaving::HeaderMap::iterator i = aHeader.begin();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment