<commit_before>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2014-2017 Baldur Karlsson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

#include "string_utils.h"
#include <ctype.h>
#include <stdint.h>
#include <wctype.h>
#include <algorithm>
#include "common/globalconfig.h"

uint32_t strhash(const char *str, uint32_t seed)
{
  if(str == NULL)
    return seed;

  uint32_t hash = seed;
  int c = *str;
  str++;

  while(c)
  {
    hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
    c = *str;
    str++;
  }

  return hash;
}

// since tolower is int -> int, this warns below. make a char -> char alternative
char toclower(char c)
{
  return (char)tolower(c);
}

char tocupper(char c)
{
  return (char)toupper(c);
}

string strlower(const string &str)
{
  string newstr(str);
  transform(newstr.begin(), newstr.end(), newstr.begin(), toclower);
  return newstr;
}

wstring strlower(const wstring &str)
{
  wstring newstr(str);
  transform(newstr.begin(), newstr.end(), newstr.begin(), towlower);
  return newstr;
}

string strupper(const string &str)
{
  string newstr(str);
  transform(newstr.begin(), newstr.end(), newstr.begin(), tocupper);
  return newstr;
}

wstring strupper(const wstring &str)
{
  wstring newstr(str);
  transform(newstr.begin(), newstr.end(), newstr.begin(), towupper);
  return newstr;
}

std::string trim(const std::string &str)
{
  const char *whitespace = "\t \n\r";
  size_t start = str.find_first_not_of(whitespace);
  size_t end = str.find_last_not_of(whitespace);

  // no non-whitespace characters, return the empty string
  if(start == std::string::npos)
    return "";

  // searching from the start found something, so searching from the end must have too.
  return str.substr(start, end - start + 1);
}

bool endswith(const std::string &value, const std::string &ending)
{
  if(ending.length() > value.length())
    return false;

  return (0 == value.compare(value.length() - ending.length(), ending.length(), ending));
}

std::string removeFromEnd(const std::string &value, const std::string &ending)
{
  string::size_type pos;
  pos = value.rfind(ending);

  // Create new string from beginning to pattern
  if(string::npos != pos)
    return value.substr(0, pos);

  // If pattern not found, just return original string
  return value;
}<commit_msg>Add unit tests for string_utils.cpp<commit_after>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2014-2017 Baldur Karlsson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

#include "string_utils.h"
#include <ctype.h>
#include <stdint.h>
#include <wctype.h>
#include <algorithm>
#include "common/globalconfig.h"

uint32_t strhash(const char *str, uint32_t seed)
{
  if(str == NULL)
    return seed;

  uint32_t hash = seed;
  int c = *str;
  str++;

  while(c)
  {
    hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
    c = *str;
    str++;
  }

  return hash;
}

// since tolower is int -> int, this warns below. make a char -> char alternative
char toclower(char c)
{
  return (char)tolower(c);
}

char tocupper(char c)
{
  return (char)toupper(c);
}

string strlower(const string &str)
{
  string newstr(str);
  transform(newstr.begin(), newstr.end(), newstr.begin(), toclower);
  return newstr;
}

wstring strlower(const wstring &str)
{
  wstring newstr(str);
  transform(newstr.begin(), newstr.end(), newstr.begin(), towlower);
  return newstr;
}

string strupper(const string &str)
{
  string newstr(str);
  transform(newstr.begin(), newstr.end(), newstr.begin(), tocupper);
  return newstr;
}

wstring strupper(const wstring &str)
{
  wstring newstr(str);
  transform(newstr.begin(), newstr.end(), newstr.begin(), towupper);
  return newstr;
}

std::string trim(const std::string &str)
{
  const char *whitespace = "\t \n\r";
  size_t start = str.find_first_not_of(whitespace);
  size_t end = str.find_last_not_of(whitespace);

  // no non-whitespace characters, return the empty string
  if(start == std::string::npos)
    return "";

  // searching from the start found something, so searching from the end must have too.
  return str.substr(start, end - start + 1);
}

bool endswith(const std::string &value, const std::string &ending)
{
  if(ending.length() > value.length())
    return false;

  return (0 == value.compare(value.length() - ending.length(), ending.length(), ending));
}

std::string removeFromEnd(const std::string &value, const std::string &ending)
{
  string::size_type pos;
  pos = value.rfind(ending);

  // Create new string from beginning to pattern
  if(string::npos != pos)
    return value.substr(0, pos);

  // If pattern not found, just return original string
  return value;
}

#if ENABLED(ENABLE_UNIT_TESTS)
#include "3rdparty/catch/catch.hpp"

TEST_CASE("String hashing", "[string]")
{
  SECTION("Same value returns the same hash")
  {
    REQUIRE(strhash("foobar") == strhash("foobar"));
    REQUIRE(strhash("blah") == strhash("blah"));
    REQUIRE(strhash("test of a long string for strhash") ==
            strhash("test of a long string for strhash"));
  };

  SECTION("Different inputs have different hashes")
  {
    REQUIRE(strhash("foobar") != strhash("blah"));
    REQUIRE(strhash("test thing") != strhash("test test test"));
    REQUIRE(strhash("test1") != strhash("test2"));
    REQUIRE(strhash("test1") != strhash("test3"));
  };

  SECTION("Same input with different seeds have different hashes")
  {
    REQUIRE(strhash("foobar", 1) != strhash("foobar", 2));
    REQUIRE(strhash("foobar", 100) != strhash("foobar", 256));
    REQUIRE(strhash("foobar", 1024) != strhash("foobar", 2048));
  };

  SECTION("Incremental hashing")
  {
    int complete = strhash("test of a long string for strhash");

    int partial = strhash("test of");
    partial = strhash(" a long", partial);
    partial = strhash(" string", partial);
    partial = strhash(" for ", partial);
    partial = strhash("strhash", partial);

    REQUIRE(partial == complete);
  };
};

TEST_CASE("String manipulation", "[string]")
{
  SECTION("strlower")
  {
    REQUIRE(strlower("foobar") == "foobar");
    REQUIRE(strlower("Foobar") == "foobar");
    REQUIRE(strlower("FOOBAR") == "foobar");
  };

  SECTION("strupper")
  {
    REQUIRE(strupper("foobar") == "FOOBAR");
    REQUIRE(strupper("Foobar") == "FOOBAR");
    REQUIRE(strupper("FOOBAR") == "FOOBAR");
  };

  SECTION("trim")
  {
    REQUIRE(trim("  foo bar  ") == "foo bar");
    REQUIRE(trim("  Foo bar") == "Foo bar");
    REQUIRE(trim("  Foo\nbar") == "Foo\nbar");
    REQUIRE(trim("FOO BAR  ") == "FOO BAR");
    REQUIRE(trim("FOO BAR  \t\n") == "FOO BAR");
  };

  SECTION("endswith / removeFromEnd")
  {
    REQUIRE(endswith("foobar", "bar"));
    REQUIRE_FALSE(endswith("foobar", "foo"));
    REQUIRE(endswith("foobar", ""));

    REQUIRE(removeFromEnd("test/foobar", "") == "test/foobar");
    REQUIRE(removeFromEnd("test/foobar", "foo") == "test/");
    REQUIRE(removeFromEnd("test/foobar", "bar") == "test/foo");
  };

  SECTION("split by comma")
  {
    std::vector<string> vec;

    split(std::string("foo,bar, blah,test"), vec, ',');

    REQUIRE(vec.size() == 4);
    REQUIRE(vec[0] == "foo");
    REQUIRE(vec[1] == "bar");
    REQUIRE(vec[2] == " blah");
    REQUIRE(vec[3] == "test");
  };

  SECTION("split by space")
  {
    std::vector<string> vec;

    split(std::string("this is a test string for   splitting! "), vec, ' ');

    REQUIRE(vec.size() == 9);
    REQUIRE(vec[0] == "this");
    REQUIRE(vec[1] == "is");
    REQUIRE(vec[2] == "a");
    REQUIRE(vec[3] == "test");
    REQUIRE(vec[4] == "string");
    REQUIRE(vec[5] == "for");
    REQUIRE(vec[6] == "");
    REQUIRE(vec[7] == "");
    REQUIRE(vec[8] == "splitting!");
  };

  SECTION("merge")
  {
    std::vector<string> vec;
    std::string str;

    merge(vec, str, ' ');
    REQUIRE(str == "");

    vec.push_back("Hello");

    merge(vec, str, ' ');
    REQUIRE(str == "Hello");

    vec.push_back("World");

    merge(vec, str, ' ');
    REQUIRE(str == "Hello World");
  };
};

#endif    // ENABLED(ENABLE_UNIT_TESTS)
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (c) 2014 Luke Parry <l.parry@warwick.ac.uk>                 *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  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 Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"

#ifndef _PreComp_
# include <sstream>
#endif

#include <gp_Ax2.hxx>
#include <Base/Console.h>
#include <Base/Writer.h>

#include "GeometryObject.h"
#include "DrawUtil.h"
#include "DrawProjGroup.h"
#include "DrawProjGroupItem.h"

#include <Mod/TechDraw/App/DrawProjGroupItemPy.h>  // generated from DrawProjGroupItemPy.xml

using namespace TechDraw;

const char* DrawProjGroupItem::TypeEnums[] = {"Front",
                                             "Left",
                                             "Right",
                                             "Rear",
                                             "Top",
                                             "Bottom",
                                             "FrontTopLeft",
                                             "FrontTopRight",
                                             "FrontBottomLeft",
                                             "FrontBottomRight",
                                             NULL};

PROPERTY_SOURCE(TechDraw::DrawProjGroupItem, TechDraw::DrawViewPart)

DrawProjGroupItem::DrawProjGroupItem(void)
{
    Type.setEnums(TypeEnums);
    ADD_PROPERTY(Type, ((long)0));
    ADD_PROPERTY_TYPE(RotationVector ,(1.0,0.0,0.0)    ,"Base",App::Prop_None,"Controls rotation of item in view. ");

    //projection group controls these
    Direction.setStatus(App::Property::ReadOnly,true);
    RotationVector.setStatus(App::Property::ReadOnly,true);
    Scale.setStatus(App::Property::ReadOnly,true);
    ScaleType.setStatus(App::Property::ReadOnly,true);
}

short DrawProjGroupItem::mustExecute() const
{
    short result = 0;
    if (!isRestoring()) {
        result  =  (Direction.isTouched()  ||
                    RotationVector.isTouched() ||
                    Source.isTouched()  ||
                    Scale.isTouched() ||
                    ScaleType.isTouched());
    }

    if (result) {
        return result;
    }
    return TechDraw::DrawViewPart::mustExecute();
}

void DrawProjGroupItem::onChanged(const App::Property *prop)
{
    TechDraw::DrawViewPart::onChanged(prop);

}

DrawProjGroupItem::~DrawProjGroupItem()
{
}

void DrawProjGroupItem::onDocumentRestored()
{
//    setAutoPos(false);                        //if restoring from file, use X,Y from file, not auto!
    App::DocumentObjectExecReturn* rc = DrawProjGroupItem::execute();
    if (rc) {
        delete rc;
    }
}

DrawProjGroup* DrawProjGroupItem::getGroup() const
{
    DrawProjGroup* result = nullptr;
    std::vector<App::DocumentObject*> parent = getInList();
    for (std::vector<App::DocumentObject*>::iterator it = parent.begin(); it != parent.end(); ++it) {
        if ((*it)->getTypeId().isDerivedFrom(DrawProjGroup::getClassTypeId())) {
            result = dynamic_cast<TechDraw::DrawProjGroup *>(*it);
            break;
        }
    }
    return result;
}
gp_Ax2 DrawProjGroupItem::getViewAxis(const Base::Vector3d& pt,
                                 const Base::Vector3d& axis,
                                 const bool flip) const
{
     gp_Ax2 viewAxis;
     Base::Vector3d x = RotationVector.getValue();
     Base::Vector3d nx = x;
     x.Normalize();
     Base::Vector3d na = axis;
     na.Normalize();
     viewAxis = TechDrawGeometry::getViewAxis(pt,axis,flip);        //default orientation

     if (!DrawUtil::checkParallel(nx,na)) {                         //!parallel/antiparallel
         viewAxis = TechDrawGeometry::getViewAxis(pt,axis,x,flip);
     }
     return viewAxis;
}

//get the angle between the current RotationVector vector and the original X dir angle
double DrawProjGroupItem::getRotateAngle()
{
    gp_Ax2 viewAxis;
    Base::Vector3d x = RotationVector.getValue();   //current rotation
    Base::Vector3d nx = x;
    x.Normalize();
    Base::Vector3d na = Direction.getValue();
    na.Normalize();
    Base::Vector3d org(0.0,0.0,0.0);

    viewAxis = TechDrawGeometry::getViewAxis(org,na,true);        //default orientation

    gp_Dir gxDir = viewAxis.XDirection();
    Base::Vector3d origX(gxDir.X(),gxDir.Y(),gxDir.Z());
    origX.Normalize();
    double dot = fabs(origX.Dot(nx));
    double angle = acos(dot);

    Base::Vector3d rotAxis = origX.Cross(nx);
    if (rotAxis == Direction.getValue()) {
        angle *= -1.0;
    }
    return angle;
}

PyObject *DrawProjGroupItem::getPyObject(void)
{
    if (PythonObject.is(Py::_None())) {
        // ref counter is set to 1
        PythonObject = Py::Object(new DrawProjGroupItemPy(this),true);
    }
    return Py::new_reference_to(PythonObject);
}
<commit_msg>Fix NaN in iso sections<commit_after>/***************************************************************************
 *   Copyright (c) 2014 Luke Parry <l.parry@warwick.ac.uk>                 *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  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 Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"

#ifndef _PreComp_
# include <sstream>
#endif

#include <gp_Ax2.hxx>
#include <Base/Console.h>
#include <Base/Writer.h>

#include "GeometryObject.h"
#include "DrawUtil.h"
#include "DrawProjGroup.h"
#include "DrawProjGroupItem.h"

#include <Mod/TechDraw/App/DrawProjGroupItemPy.h>  // generated from DrawProjGroupItemPy.xml

using namespace TechDraw;

const char* DrawProjGroupItem::TypeEnums[] = {"Front",
                                             "Left",
                                             "Right",
                                             "Rear",
                                             "Top",
                                             "Bottom",
                                             "FrontTopLeft",
                                             "FrontTopRight",
                                             "FrontBottomLeft",
                                             "FrontBottomRight",
                                             NULL};

PROPERTY_SOURCE(TechDraw::DrawProjGroupItem, TechDraw::DrawViewPart)

DrawProjGroupItem::DrawProjGroupItem(void)
{
    Type.setEnums(TypeEnums);
    ADD_PROPERTY(Type, ((long)0));
    ADD_PROPERTY_TYPE(RotationVector ,(1.0,0.0,0.0)    ,"Base",App::Prop_None,"Controls rotation of item in view. ");

    //projection group controls these
    Direction.setStatus(App::Property::ReadOnly,true);
    RotationVector.setStatus(App::Property::ReadOnly,true);
    Scale.setStatus(App::Property::ReadOnly,true);
    ScaleType.setStatus(App::Property::ReadOnly,true);
}

short DrawProjGroupItem::mustExecute() const
{
    short result = 0;
    if (!isRestoring()) {
        result  =  (Direction.isTouched()  ||
                    RotationVector.isTouched() ||
                    Source.isTouched()  ||
                    Scale.isTouched() ||
                    ScaleType.isTouched());
    }

    if (result) {
        return result;
    }
    return TechDraw::DrawViewPart::mustExecute();
}

void DrawProjGroupItem::onChanged(const App::Property *prop)
{
    TechDraw::DrawViewPart::onChanged(prop);

}

DrawProjGroupItem::~DrawProjGroupItem()
{
}

void DrawProjGroupItem::onDocumentRestored()
{
//    setAutoPos(false);                        //if restoring from file, use X,Y from file, not auto!
    App::DocumentObjectExecReturn* rc = DrawProjGroupItem::execute();
    if (rc) {
        delete rc;
    }
}

DrawProjGroup* DrawProjGroupItem::getGroup() const
{
    DrawProjGroup* result = nullptr;
    std::vector<App::DocumentObject*> parent = getInList();
    for (std::vector<App::DocumentObject*>::iterator it = parent.begin(); it != parent.end(); ++it) {
        if ((*it)->getTypeId().isDerivedFrom(DrawProjGroup::getClassTypeId())) {
            result = dynamic_cast<TechDraw::DrawProjGroup *>(*it);
            break;
        }
    }
    return result;
}
gp_Ax2 DrawProjGroupItem::getViewAxis(const Base::Vector3d& pt,
                                 const Base::Vector3d& axis,
                                 const bool flip) const
{
     gp_Ax2 viewAxis;
     Base::Vector3d x = RotationVector.getValue();
     Base::Vector3d nx = x;
     x.Normalize();
     Base::Vector3d na = axis;
     na.Normalize();
     viewAxis = TechDrawGeometry::getViewAxis(pt,axis,flip);        //default orientation

     if (!DrawUtil::checkParallel(nx,na)) {                         //!parallel/antiparallel
         viewAxis = TechDrawGeometry::getViewAxis(pt,axis,x,flip);
     }
     return viewAxis;
}

//get the angle between the current RotationVector vector and the original X dir angle
double DrawProjGroupItem::getRotateAngle()
{
    gp_Ax2 viewAxis;
    Base::Vector3d x = RotationVector.getValue();   //current rotation
    Base::Vector3d nx = x;
    nx.Normalize();
    Base::Vector3d na = Direction.getValue();
    na.Normalize();
    Base::Vector3d org(0.0,0.0,0.0);

    viewAxis = TechDrawGeometry::getViewAxis(org,na,true);        //default orientation

    gp_Dir gxDir = viewAxis.XDirection();
    Base::Vector3d origX(gxDir.X(),gxDir.Y(),gxDir.Z());
    origX.Normalize();
    double dot = fabs(origX.Dot(nx));
    double angle = acos(dot);

    Base::Vector3d rotAxis = origX.Cross(nx);
    if (rotAxis == Direction.getValue()) {
        angle *= -1.0;
    }
    return angle;
}

PyObject *DrawProjGroupItem::getPyObject(void)
{
    if (PythonObject.is(Py::_None())) {
        // ref counter is set to 1
        PythonObject = Py::Object(new DrawProjGroupItemPy(this),true);
    }
    return Py::new_reference_to(PythonObject);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */
#include <cassert>
#include <cstdlib>
#include <vector>
#include <zlib.h>
#include "h2o.h"
#include "encode.h"

namespace {
    class brotli_context : public h2o_compress_context_t {
    protected:
        brotli::BrotliCompressor *brotli_;
        brotli::BrotliParams params_;
        std::vector<h2o_iovec_t> bufs_; // all bufs_[nnn].base must be free(3)ed
        h2o_mem_pool_t *pool_;
    public:
        brotli_context(h2o_mem_pool_t *pool, int quality, size_t estimated_content_length) : brotli_(NULL) {
            name = h2o_iovec_t::create(H2O_STRLIT("br"));
            compress = _compress;
            params_.quality = quality;
            pool_ = pool;
            if (estimated_content_length != std::numeric_limits<size_t>::max())
                _update_lgwin(params_, estimated_content_length);
        }
        ~brotli_context() {
            delete brotli_;
        }
        static void dispose(void *_self) {
            brotli_context *self = static_cast<brotli_context *>(_self);
            self->~brotli_context();
        }
    private:
        void _emit(bool is_last, bool force_flush);
        void _compress(h2o_iovec_t *inbufs, size_t inbufcnt, int is_final, h2o_iovec_t **outbufs, size_t *outbufcnt);
        static void _compress(h2o_compress_context_t *self, h2o_iovec_t *inbufs, size_t inbufcnt, int is_final,
                              h2o_iovec_t **outbufs, size_t *outbufcnt) {
            static_cast<brotli_context*>(self)->_compress(inbufs, inbufcnt, is_final, outbufs, outbufcnt);
        }
        static void _update_lgwin(brotli::BrotliParams &params, size_t estimated_content_length);
    };
}

void brotli_context::_emit(bool is_last, bool force_flush)
{
    uint8_t *output;
    size_t out_size;
    bool ret = brotli_->WriteBrotliData(is_last, force_flush, &out_size, &output);
    assert(ret);
    if (out_size != 0)
        bufs_.push_back(h2o_strdup(this->pool_, reinterpret_cast<const char *>(output), out_size));
}

void brotli_context::_compress(h2o_iovec_t *inbufs, size_t inbufcnt, int is_final, h2o_iovec_t **outbufs, size_t *outbufcnt)
{
    if (brotli_ == NULL) {
        if (is_final) {
            uint64_t len = 0;
            for (size_t i = 0; i != inbufcnt; ++i)
                len += inbufs[i].len;
            if (len < std::numeric_limits<size_t>::max())
                _update_lgwin(params_, len);
        }
        brotli_ = new brotli::BrotliCompressor(params_);
    }

    bufs_.clear();

    if (inbufcnt != 0) {
        size_t inbufindex = 0, offset = 0, block_space = brotli_->input_block_size();
        while (inbufindex != inbufcnt) {
            size_t copy_len = std::min(block_space, inbufs[inbufindex].len - offset);
            brotli_->CopyInputToRingBuffer(copy_len, reinterpret_cast<const uint8_t *>(inbufs[inbufindex].base) + offset);
            offset += copy_len;
            if (inbufs[inbufindex].len == offset)
                if (++inbufindex == inbufcnt)
                    break;
            if (block_space == 0) {
                _emit(false, false);
                block_space = brotli_->input_block_size();
            }
        }
        _emit(is_final, !is_final);
    } else {
        if (is_final)
            _emit(true, false);
    }

    if (is_final) {
        delete brotli_;
        brotli_ = NULL;
    }

    *outbufs = &bufs_.front();
    *outbufcnt = bufs_.size();
}

void brotli_context::_update_lgwin(brotli::BrotliParams &params, size_t estimated_content_length)
{
    int bits = estimated_content_length > 1 ? sizeof(unsigned long long) * 8 - __builtin_clzll(estimated_content_length - 1) : 1;
    if (bits < params.lgwin)
        params.lgwin = std::max(bits, brotli::kMinWindowBits);
}

h2o_compress_context_t *h2o_compress_brotli_open(h2o_mem_pool_t *pool, int quality, size_t estimated_content_length)
{
    assert(pool != nullptr);
    auto ctx = pool->alloc_shared_for<brotli_context>(1, brotli_context::dispose);
    return new (ctx) brotli_context(pool, quality, estimated_content_length);
}
<commit_msg>fix SEGV while trying to encode multiple vectors<commit_after>/*
 * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */
#include <cassert>
#include <cstdlib>
#include <vector>
#include <zlib.h>
#include "h2o.h"
#include "encode.h"

namespace {
    class brotli_context : public h2o_compress_context_t {
    protected:
        brotli::BrotliCompressor *brotli_;
        brotli::BrotliParams params_;
        std::vector<h2o_iovec_t> bufs_; // all bufs_[nnn].base must be free(3)ed
        h2o_mem_pool_t *pool_;
    public:
        brotli_context(h2o_mem_pool_t *pool, int quality, size_t estimated_content_length) : brotli_(NULL) {
            name = h2o_iovec_t::create(H2O_STRLIT("br"));
            compress = _compress;
            params_.quality = quality;
            pool_ = pool;
            if (estimated_content_length != std::numeric_limits<size_t>::max())
                _update_lgwin(params_, estimated_content_length);
        }
        ~brotli_context() {
            delete brotli_;
        }
        static void dispose(void *_self) {
            brotli_context *self = static_cast<brotli_context *>(_self);
            self->~brotli_context();
        }
    private:
        void _emit(bool is_last, bool force_flush);
        void _compress(h2o_iovec_t *inbufs, size_t inbufcnt, int is_final, h2o_iovec_t **outbufs, size_t *outbufcnt);
        static void _compress(h2o_compress_context_t *self, h2o_iovec_t *inbufs, size_t inbufcnt, int is_final,
                              h2o_iovec_t **outbufs, size_t *outbufcnt) {
            static_cast<brotli_context*>(self)->_compress(inbufs, inbufcnt, is_final, outbufs, outbufcnt);
        }
        static void _update_lgwin(brotli::BrotliParams &params, size_t estimated_content_length);
    };
}

void brotli_context::_emit(bool is_last, bool force_flush)
{
    uint8_t *output;
    size_t out_size;
    bool ret = brotli_->WriteBrotliData(is_last, force_flush, &out_size, &output);
    assert(ret);
    if (out_size != 0)
        bufs_.push_back(h2o_strdup(this->pool_, reinterpret_cast<const char *>(output), out_size));
}

void brotli_context::_compress(h2o_iovec_t *inbufs, size_t inbufcnt, int is_final, h2o_iovec_t **outbufs, size_t *outbufcnt)
{
    if (brotli_ == NULL) {
        if (is_final) {
            uint64_t len = 0;
            for (size_t i = 0; i != inbufcnt; ++i)
                len += inbufs[i].len;
            if (len < std::numeric_limits<size_t>::max())
                _update_lgwin(params_, len);
        }
        brotli_ = new brotli::BrotliCompressor(params_);
    }

    bufs_.clear();

    if (inbufcnt != 0) {
        size_t inbufindex = 0, offset = 0, block_space = brotli_->input_block_size();
        while (inbufindex != inbufcnt) {
            size_t copy_len = std::min(block_space, inbufs[inbufindex].len - offset);
            brotli_->CopyInputToRingBuffer(copy_len, reinterpret_cast<const uint8_t *>(inbufs[inbufindex].base) + offset);
            offset += copy_len;
            if (inbufs[inbufindex].len == offset) {
                if (++inbufindex == inbufcnt)
                    break;
                offset = 0;
            }
            if (block_space == 0) {
                _emit(false, false);
                block_space = brotli_->input_block_size();
            }
        }
        _emit(is_final, !is_final);
    } else {
        if (is_final)
            _emit(true, false);
    }

    if (is_final) {
        delete brotli_;
        brotli_ = NULL;
    }

    *outbufs = &bufs_.front();
    *outbufcnt = bufs_.size();
}

void brotli_context::_update_lgwin(brotli::BrotliParams &params, size_t estimated_content_length)
{
    int bits = estimated_content_length > 1 ? sizeof(unsigned long long) * 8 - __builtin_clzll(estimated_content_length - 1) : 1;
    if (bits < params.lgwin)
        params.lgwin = std::max(bits, brotli::kMinWindowBits);
}

h2o_compress_context_t *h2o_compress_brotli_open(h2o_mem_pool_t *pool, int quality, size_t estimated_content_length)
{
    assert(pool != nullptr);
    auto ctx = pool->alloc_shared_for<brotli_context>(1, brotli_context::dispose);
    return new (ctx) brotli_context(pool, quality, estimated_content_length);
}
<|endoftext|>


<commit_before>#ifndef SRC_ERRORS_H_
#define SRC_ERRORS_H_

#include <stdexcept>
#include <string>

namespace CthunAgent {

/// Base error class.
class agent_error : public std::runtime_error {
  public:
    explicit agent_error(std::string const& msg) : std::runtime_error(msg) {}
};

/// Fatal error class.
class fatal_error : public agent_error {
  public:
    explicit fatal_error(std::string const& msg) : agent_error(msg) {}
};

/// Error thrown when loading modules.
class module_error : public agent_error {
  public:
    explicit module_error(std::string const& msg) : agent_error(msg) {}
};

/// Generic file error class.
class file_error : public agent_error {
  public:
    explicit file_error(std::string const& msg) : agent_error(msg) {}
};

//
// CNC request errors
//

class request_error : public agent_error {
  public:
    explicit request_error(std::string const& msg) : agent_error(msg) {}
};

/// Error due to an invalid request message.
class request_validation_error : public request_error {
  public:
    explicit request_validation_error(std::string const& msg)
            : request_error(msg) {}
};

/// Error due to a failure during the processing of a request message.
class request_processing_error : public request_error {
  public:
    explicit request_processing_error(std::string const& msg)
            : request_error(msg) {}
};

//
// Configuration container errors
//

class configuration_error : public agent_error {
  public:
    explicit configuration_error(std::string const& msg)
            : agent_error(msg) {}
};

/// Error thrown when trying to set the configuration object before
/// initializing it.
class uninitialized_error : public configuration_error {
  public:
    explicit uninitialized_error(std::string const& msg)
            : configuration_error(msg) {}
};

/// Error thrown when referring to an unknown configuration entry or
/// trying to set an invalid value to a known entry.
class configuration_entry_error : public configuration_error {
  public:
    explicit configuration_entry_error(std::string const& msg)
            : configuration_error(msg) {}
};

/// Error thrown when config file doesn't exist.
class no_configfile_error : public configuration_error {
  public:
    explicit no_configfile_error(std::string const& msg)
            : configuration_error(msg) {}
};

/// Error thrown when required config variable isn't set.
class required_not_set_error : public configuration_error {
  public:
    explicit required_not_set_error(std::string const& msg)
        : configuration_error(msg) {}
};

/// Error thrown when cli parse error occurs.
class cli_parse_error : public configuration_error {
  public:
    explicit cli_parse_error(std::string const& msg)
            : configuration_error(msg) {}
};

}  // namespace CthunAgent

#endif  // SRC_ERRORS_H_
<commit_msg>(maint) Rename "cnc" to "rpc"<commit_after>#ifndef SRC_ERRORS_H_
#define SRC_ERRORS_H_

#include <stdexcept>
#include <string>

namespace CthunAgent {

/// Base error class.
class agent_error : public std::runtime_error {
  public:
    explicit agent_error(std::string const& msg) : std::runtime_error(msg) {}
};

/// Fatal error class.
class fatal_error : public agent_error {
  public:
    explicit fatal_error(std::string const& msg) : agent_error(msg) {}
};

/// Error thrown when loading modules.
class module_error : public agent_error {
  public:
    explicit module_error(std::string const& msg) : agent_error(msg) {}
};

/// Generic file error class.
class file_error : public agent_error {
  public:
    explicit file_error(std::string const& msg) : agent_error(msg) {}
};

//
// RPC request errors
//

class request_error : public agent_error {
  public:
    explicit request_error(std::string const& msg) : agent_error(msg) {}
};

/// Error due to an invalid request message.
class request_validation_error : public request_error {
  public:
    explicit request_validation_error(std::string const& msg)
            : request_error(msg) {}
};

/// Error due to a failure during the processing of a request message.
class request_processing_error : public request_error {
  public:
    explicit request_processing_error(std::string const& msg)
            : request_error(msg) {}
};

//
// Configuration container errors
//

class configuration_error : public agent_error {
  public:
    explicit configuration_error(std::string const& msg)
            : agent_error(msg) {}
};

/// Error thrown when trying to set the configuration object before
/// initializing it.
class uninitialized_error : public configuration_error {
  public:
    explicit uninitialized_error(std::string const& msg)
            : configuration_error(msg) {}
};

/// Error thrown when referring to an unknown configuration entry or
/// trying to set an invalid value to a known entry.
class configuration_entry_error : public configuration_error {
  public:
    explicit configuration_entry_error(std::string const& msg)
            : configuration_error(msg) {}
};

/// Error thrown when config file doesn't exist.
class no_configfile_error : public configuration_error {
  public:
    explicit no_configfile_error(std::string const& msg)
            : configuration_error(msg) {}
};

/// Error thrown when required config variable isn't set.
class required_not_set_error : public configuration_error {
  public:
    explicit required_not_set_error(std::string const& msg)
        : configuration_error(msg) {}
};

/// Error thrown when cli parse error occurs.
class cli_parse_error : public configuration_error {
  public:
    explicit cli_parse_error(std::string const& msg)
            : configuration_error(msg) {}
};

}  // namespace CthunAgent

#endif  // SRC_ERRORS_H_
<|endoftext|>


<commit_before>// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

#include "iceoryx_posh/internal/roudi_environment/roudi_environment.hpp"

#include "test.hpp"

using namespace ::testing;
using namespace iox::roudi;
using ::testing::Return;

class RouDiEnvironment_test : public Test
{
  public:
    void SetUp(){};
    void TearDown(){};
};

TEST_F(RouDiEnvironment_test, StartingRouDiTwiceLeadsToError)
{
    RouDiEnvironment m_sut{iox::RouDiConfig_t().setDefaults()};
    EXPECT_DEATH({ RouDiEnvironment m_sut2; }, ".*");
}
<commit_msg>iox-#611 Don't use default c'tor<commit_after>// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

#include "iceoryx_posh/internal/roudi_environment/roudi_environment.hpp"

#include "test.hpp"

using namespace ::testing;
using namespace iox::roudi;
using ::testing::Return;

class RouDiEnvironment_test : public Test
{
  public:
    void SetUp(){};
    void TearDown(){};
};

TEST_F(RouDiEnvironment_test, StartingRouDiTwiceLeadsToError)
{
    RouDiEnvironment m_sut{iox::RouDiConfig_t().setDefaults()};
    EXPECT_DEATH({ RouDiEnvironment m_sut2{iox::RouDiConfig_t().setDefaults()}; }, ".*");
}
<|endoftext|>


<commit_before>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "integrations/tensorflow/compiler/Passes.h"
#include "iree/base/signature_mangle.h"
#include "iree/compiler/Dialect/Flow/IR/FlowDialect.h"
#include "iree/compiler/Dialect/Flow/IR/FlowOps.h"
#include "llvm/ADT/STLExtras.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/IR/SymbolTable.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Pass/PassRegistry.h"
#include "mlir/Support/LLVM.h"
#include "mlir/Support/LogicalResult.h"
#include "mlir/Transforms/Utils.h"
#include "tensorflow/compiler/mlir/tensorflow/ir/tf_ops.h"
#include "tensorflow/compiler/mlir/tensorflow/ir/tf_saved_model.h"

namespace mlir {
namespace iree_compiler {

namespace {

LogicalResult ImportTfSavedModelGlobalTensorsToIREEFlow(ModuleOp module) {
  OpBuilder global_builder(module.getBodyRegion());
  SymbolTable symbol_table(module);

  DenseMap<StringRef, std::string> sym_name_to_flow_sym_name;
  for (auto global_tensor : module.getOps<tf_saved_model::GlobalTensorOp>()) {
    auto exported_names = tf_saved_model::GetExportedNames(global_tensor);
    std::string flow_sym_name;
    if (exported_names.empty()) {
      flow_sym_name = "__iree_flow_" + global_tensor.sym_name().str();
    } else if (exported_names.size() == 1) {
      flow_sym_name = exported_names[0].str();
    } else {
      return global_tensor.emitError()
             << "Multiple exported names for global tensor not supported yet";
    }
    sym_name_to_flow_sym_name[global_tensor.sym_name()] = flow_sym_name;
    global_builder.create<IREE::Flow::VariableOp>(
        global_tensor.getLoc(), flow_sym_name, global_tensor.is_mutable(),
        global_tensor.type(), global_tensor.value());
  }

  for (auto func : module.getOps<FuncOp>()) {
    SmallVector<unsigned, 4> args_to_erase;
    for (int i = 0, e = func.getNumArguments(); i < e; i++) {
      tf_saved_model::GlobalTensorOp global_tensor =
          tf_saved_model::LookupBoundInput(func, i, symbol_table);
      if (!global_tensor) {
        continue;
      }
      args_to_erase.push_back(i);
      auto flow_sym_ref = global_builder.getSymbolRefAttr(
          sym_name_to_flow_sym_name[global_tensor.sym_name()]);
      Value arg = func.getArgument(i);
      if (global_tensor.is_mutable()) {
        // The value is a tensor<*x!tf.resource> type, which flows into
        // tf.ReadVariableOp/tf.AssignVariableOp.
        // XLA resource functionalization should have canonicalized everything
        // to uses of those two ops in the body of the tf_saved_model exported
        // function.
        for (OpOperand &operand : llvm::make_early_inc_range(arg.getUses())) {
          if (auto read_variable =
                  dyn_cast<TF::ReadVariableOp>(operand.getOwner())) {
            auto load = OpBuilder(read_variable)
                            .create<IREE::Flow::VariableLoadOp>(
                                read_variable.getLoc(),
                                read_variable.value().getType(), flow_sym_ref);
            read_variable.value().replaceAllUsesWith(load.result());
            read_variable.erase();
            continue;
          }
          if (auto assign_variable =
                  dyn_cast<TF::AssignVariableOp>(operand.getOwner())) {
            OpBuilder(assign_variable)
                .create<IREE::Flow::VariableStoreOp>(assign_variable.getLoc(),
                                                     assign_variable.value(),
                                                     flow_sym_ref);
            assign_variable.erase();
            continue;
          }
          return operand.getOwner()->emitError()
                 << "unknown op operating on resource for global tensor : "
                 << operand.getOwner()->getName();
        }
      } else {
        // The value is already a tensor value type. Just RAUW it with a
        // `flow.variable.load`.
        auto load =
            OpBuilder(func.getBody())
                .create<IREE::Flow::VariableLoadOp>(
                    global_tensor.getLoc(), arg.getType(), flow_sym_ref);
        arg.replaceAllUsesWith(load.result());
      }
    }
    func.eraseArguments(args_to_erase);
  }

  // Erase all the global tensors.
  for (auto global_tensor : llvm::make_early_inc_range(
           module.getOps<tf_saved_model::GlobalTensorOp>())) {
    global_tensor.erase();
  }
  return success();
}

}  // namespace

class TFSavedModelLowerGlobalTensors
    : public ModulePass<TFSavedModelLowerGlobalTensors> {
 public:
  void runOnModule() override {
    if (failed(ImportTfSavedModelGlobalTensorsToIREEFlow(getModule()))) {
      signalPassFailure();
    }
  }
};

std::unique_ptr<OpPassBase<ModuleOp>> createTFSavedModelLowerGlobalTensors() {
  return std::make_unique<TFSavedModelLowerGlobalTensors>();
}

static PassRegistration<TFSavedModelLowerGlobalTensors> pass(
    "iree-tf-saved-model-lower-global-tensors",
    "Lowers tf_saved_model global tensors to flow dialect.");

}  // namespace iree_compiler
}  // namespace mlir
<commit_msg>Fix naming convention to match llvm style<commit_after>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "integrations/tensorflow/compiler/Passes.h"
#include "iree/base/signature_mangle.h"
#include "iree/compiler/Dialect/Flow/IR/FlowDialect.h"
#include "iree/compiler/Dialect/Flow/IR/FlowOps.h"
#include "llvm/ADT/STLExtras.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/IR/SymbolTable.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Pass/PassRegistry.h"
#include "mlir/Support/LLVM.h"
#include "mlir/Support/LogicalResult.h"
#include "mlir/Transforms/Utils.h"
#include "tensorflow/compiler/mlir/tensorflow/ir/tf_ops.h"
#include "tensorflow/compiler/mlir/tensorflow/ir/tf_saved_model.h"

namespace mlir {
namespace iree_compiler {

static LogicalResult importTfSavedModelGlobalTensorsToIREEFlow(
    ModuleOp module) {
  OpBuilder globalBuilder(module.getBodyRegion());
  SymbolTable symbolTable(module);

  DenseMap<StringRef, std::string> symNameToFlowSymName;
  for (auto globalTensor : module.getOps<tf_saved_model::GlobalTensorOp>()) {
    auto exportedNames = tf_saved_model::GetExportedNames(globalTensor);
    std::string flowSymName;
    if (exportedNames.empty()) {
      flowSymName = "__iree_flow_" + globalTensor.sym_name().str();
    } else if (exportedNames.size() == 1) {
      flowSymName = exportedNames[0].str();
    } else {
      return globalTensor.emitError()
             << "Multiple exported names for global tensor not supported yet";
    }
    symNameToFlowSymName[globalTensor.sym_name()] = flowSymName;
    globalBuilder.create<IREE::Flow::VariableOp>(
        globalTensor.getLoc(), flowSymName, globalTensor.is_mutable(),
        globalTensor.type(), globalTensor.value());
  }

  for (auto func : module.getOps<FuncOp>()) {
    SmallVector<unsigned, 4> argsToErase;
    for (int i = 0, e = func.getNumArguments(); i < e; i++) {
      tf_saved_model::GlobalTensorOp globalTensor =
          tf_saved_model::LookupBoundInput(func, i, symbolTable);
      if (!globalTensor) {
        continue;
      }
      argsToErase.push_back(i);
      auto flowSymRef = globalBuilder.getSymbolRefAttr(
          symNameToFlowSymName[globalTensor.sym_name()]);
      Value arg = func.getArgument(i);
      if (globalTensor.is_mutable()) {
        // The value is a tensor<*x!tf.resource> type, which flows into
        // tf.ReadVariableOp/tf.AssignVariableOp.
        // XLA resource functionalization should have canonicalized everything
        // to uses of those two ops in the body of the tf_saved_model exported
        // function.
        for (OpOperand &operand : llvm::make_early_inc_range(arg.getUses())) {
          if (auto readVariable =
                  dyn_cast<TF::ReadVariableOp>(operand.getOwner())) {
            auto load = OpBuilder(readVariable)
                            .create<IREE::Flow::VariableLoadOp>(
                                readVariable.getLoc(),
                                readVariable.value().getType(), flowSymRef);
            readVariable.value().replaceAllUsesWith(load.result());
            readVariable.erase();
            continue;
          }
          if (auto assignVariable =
                  dyn_cast<TF::AssignVariableOp>(operand.getOwner())) {
            OpBuilder(assignVariable)
                .create<IREE::Flow::VariableStoreOp>(assignVariable.getLoc(),
                                                     assignVariable.value(),
                                                     flowSymRef);
            assignVariable.erase();
            continue;
          }
          return operand.getOwner()->emitError()
                 << "unknown op operating on resource for global tensor : "
                 << operand.getOwner()->getName();
        }
      } else {
        // The value is already a tensor value type. Just RAUW it with a
        // `flow.variable.load`.
        auto load = OpBuilder(func.getBody())
                        .create<IREE::Flow::VariableLoadOp>(
                            globalTensor.getLoc(), arg.getType(), flowSymRef);
        arg.replaceAllUsesWith(load.result());
      }
    }
    func.eraseArguments(argsToErase);
  }

  // Erase all the global tensors.
  for (auto globalTensor : llvm::make_early_inc_range(
           module.getOps<tf_saved_model::GlobalTensorOp>())) {
    globalTensor.erase();
  }
  return success();
}

class TFSavedModelLowerGlobalTensors
    : public ModulePass<TFSavedModelLowerGlobalTensors> {
 public:
  void runOnModule() override {
    if (failed(importTfSavedModelGlobalTensorsToIREEFlow(getModule()))) {
      signalPassFailure();
    }
  }
};

std::unique_ptr<OpPassBase<ModuleOp>> createTFSavedModelLowerGlobalTensors() {
  return std::make_unique<TFSavedModelLowerGlobalTensors>();
}

static PassRegistration<TFSavedModelLowerGlobalTensors> pass(
    "iree-tf-saved-model-lower-global-tensors",
    "Lowers tf_saved_model global tensors to flow dialect.");

}  // namespace iree_compiler
}  // namespace mlir
<|endoftext|>


<commit_before>/*
    Copyright (c) 2006 Volker Krause <volker.krause@rwth-aachen.de>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 of the License, or (at your
    option) any later version.

    This library 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 Library General Public
    License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "collection.h"
#include "collectionselectjob.h"
#include "imapparser.h"
#include "messagefetchjob.h"

#include "kmime_message.h"

#include <QDebug>

using namespace PIM;

class PIM::MessageFetchJobPrivate
{
  public:
    QByteArray path;
    DataReference uid;
    Message::List messages;
    QByteArray tag;
};

PIM::MessageFetchJob::MessageFetchJob( const QByteArray & path, QObject * parent ) :
    Job( parent ),
    d( new MessageFetchJobPrivate )
{
  d->path = path;
}

PIM::MessageFetchJob::MessageFetchJob( const DataReference & ref, QObject * parent ) :
    Job( parent ),
    d( new MessageFetchJobPrivate )
{
  d->path = Collection::root();
  d->uid = ref;
}

PIM::MessageFetchJob::~ MessageFetchJob( )
{
  delete d;
}

void PIM::MessageFetchJob::doStart()
{
  CollectionSelectJob *job = new CollectionSelectJob( d->uid.isNull() ? d->path : Collection::root(), this );
  connect( job, SIGNAL(done(PIM::Job*)), SLOT(selectDone(PIM::Job*)) );
  job->start();
}

void PIM::MessageFetchJob::handleResponse( const QByteArray & tag, const QByteArray & data )
{
  if ( tag == d->tag ) {
    if ( !data.startsWith( "OK" ) )
      setError( Unknown );
    emit done( this );
    return;
  }
  if ( tag == "*" ) {
    int begin = data.indexOf( "FETCH" );
    if ( begin >= 0 ) {
      // create a new message object
      Message* msg = new Message(); // TODO: UID
      KMime::Message* mime = new KMime::Message();
      msg->setMime( mime );
      d->messages.append( msg );

      // parse the main fetch response
      QList<QByteArray> fetch = ImapParser::parseParentheziedList( data, begin + 6 );
      for ( int i = 0; i < fetch.count() - 1; ++i ) {
        // envelope
        if ( fetch[i] == "ENVELOPE" ) {
          QList<QByteArray> env = ImapParser::parseParentheziedList( fetch[i + 1] );
          // date
          mime->date()->from7BitString( env[0] );
          // subject
          mime->subject()->from7BitString( env[1] );
        }
      }
      return;
    }
  }
  qDebug() << "Unhandled response in message fetch job: " << tag << data;
}

Message::List PIM::MessageFetchJob::messages() const
{
  return d->messages;
}

void PIM::MessageFetchJob::selectDone( PIM::Job * job )
{
  if ( job->error() ) {
    setError( job->error() );
    emit done( this );
  } else {
    job->deleteLater();
    // the collection is now selected, fetch the message(s)
    d->tag = newTag();
    QByteArray command = d->tag + " FETCH ";
    if ( d->uid.isNull() )
      command += "0:* ENVELOPE";
    else
      command += d->uid.persistanceID().toLatin1() + " (BODY[])";
    writeData( command );
  }
}

#include "messagefetchjob.moc"
<commit_msg>Parsing of from and reply-to fields in envelope response. Shows a very strange bug in libkmime...<commit_after>/*
    Copyright (c) 2006 Volker Krause <volker.krause@rwth-aachen.de>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 of the License, or (at your
    option) any later version.

    This library 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 Library General Public
    License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "collection.h"
#include "collectionselectjob.h"
#include "imapparser.h"
#include "messagefetchjob.h"

#include "kmime_message.h"

#include <QDebug>

using namespace PIM;

class PIM::MessageFetchJobPrivate
{
  public:
    QByteArray path;
    DataReference uid;
    Message::List messages;
    QByteArray tag;
};

PIM::MessageFetchJob::MessageFetchJob( const QByteArray & path, QObject * parent ) :
    Job( parent ),
    d( new MessageFetchJobPrivate )
{
  d->path = path;
}

PIM::MessageFetchJob::MessageFetchJob( const DataReference & ref, QObject * parent ) :
    Job( parent ),
    d( new MessageFetchJobPrivate )
{
  d->path = Collection::root();
  d->uid = ref;
}

PIM::MessageFetchJob::~ MessageFetchJob( )
{
  delete d;
}

void PIM::MessageFetchJob::doStart()
{
  CollectionSelectJob *job = new CollectionSelectJob( d->uid.isNull() ? d->path : Collection::root(), this );
  connect( job, SIGNAL(done(PIM::Job*)), SLOT(selectDone(PIM::Job*)) );
  job->start();
}

void PIM::MessageFetchJob::handleResponse( const QByteArray & tag, const QByteArray & data )
{
  if ( tag == d->tag ) {
    if ( !data.startsWith( "OK" ) )
      setError( Unknown );
    emit done( this );
    return;
  }
  if ( tag == "*" ) {
    int begin = data.indexOf( "FETCH" );
    if ( begin >= 0 ) {
      // create a new message object
      Message* msg = new Message(); // TODO: UID
      KMime::Message* mime = new KMime::Message();
      msg->setMime( mime );
      d->messages.append( msg );

      // parse the main fetch response
      QList<QByteArray> fetch = ImapParser::parseParentheziedList( data, begin + 6 );
      for ( int i = 0; i < fetch.count() - 1; ++i ) {
        // envelope
        if ( fetch[i] == "ENVELOPE" ) {
          QList<QByteArray> env = ImapParser::parseParentheziedList( fetch[i + 1] );
          Q_ASSERT( env.count() >= 4 );
          // date
          mime->date()->from7BitString( env[0] );
          // subject
          mime->subject()->from7BitString( env[1] );
          // from
          QList<QByteArray> addrList = ImapParser::parseParentheziedList( env[2] );
          if ( addrList.count() >= 1 ) {
            QList<QByteArray> addr = ImapParser::parseParentheziedList( addrList[0] );
            Q_ASSERT( addr.count() == 4 );
            mime->from()->setName( addr[0] );
            mime->from()->setEmail( addr[2] + "@" + addr[3] );
          }
          // reply-to
          addrList = ImapParser::parseParentheziedList( env[3] );
          if ( addrList.count() >= 1 ) {
            QList<QByteArray> addr = ImapParser::parseParentheziedList( addrList[0] );
            Q_ASSERT( addr.count() == 4 );
            mime->replyTo()->setNameFrom7Bit( addr[0] );
            mime->replyTo()->setEmail( addr[2] + "@" + addr[3] );
          }
        }
      }
      return;
    }
  }
  qDebug() << "Unhandled response in message fetch job: " << tag << data;
}

Message::List PIM::MessageFetchJob::messages() const
{
  return d->messages;
}

void PIM::MessageFetchJob::selectDone( PIM::Job * job )
{
  if ( job->error() ) {
    setError( job->error() );
    emit done( this );
  } else {
    job->deleteLater();
    // the collection is now selected, fetch the message(s)
    d->tag = newTag();
    QByteArray command = d->tag + " FETCH ";
    if ( d->uid.isNull() )
      command += "0:* ENVELOPE";
    else
      command += d->uid.persistanceID().toLatin1() + " (BODY[])";
    writeData( command );
  }
}

#include "messagefetchjob.moc"
<|endoftext|>


<commit_before>// @(#)root/tree:$Name:  $:$Id: TTreeCloner.cxx,v 1.9 2006/07/06 17:42:59 pcanal Exp $
// Author: Philippe Canal 07/11/2005

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TTreeCloner                                                          //
//                                                                      //
// Class implementing or helping  the various TTree cloning method      //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TBasket.h"
#include "TBranch.h"
#include "TBranchClones.h"
#include "TBranchElement.h"
#include "TStreamerInfo.h"
#include "TBranchRef.h"
#include "TError.h"
#include "TProcessID.h"
#include "TTree.h"
#include "TTreeCloner.h"
#include "TFile.h"
#include "TLeafI.h"
#include "TLeafL.h"

TTreeCloner::TTreeCloner(TTree *from, TTree *to, Option_t *method) :
   fIsValid(kTRUE),
   fFromTree(from),
   fToTree(to),
   fMethod(method),
   fFromBranches( from ? from->GetListOfLeaves()->GetEntries()+1 : 0),
   fToBranches( to ? from->GetListOfLeaves()->GetEntries()+1 : 0),
   fMaxBaskets(CollectBranches()),
   fBasketBranchNum(new UInt_t[fMaxBaskets]),
   fBasketNum(new UInt_t[fMaxBaskets]),
   fBasketSeek(new Long64_t[fMaxBaskets]),
   fBasketEntry(new Long64_t[fMaxBaskets]),
   fBasketIndex(new Int_t[fMaxBaskets]),
   fCloneMethod(TTreeCloner::kDefault),
   fToStartEntries(0)
{
   // Constructor.  This object would transfer the data from
   // 'from' to 'to' using the method indicated in method.

   TString opt(method);
   opt.ToLower();
   if (opt.Contains("sortbasketsbybranch")) {
      //::Info("TTreeCloner::TTreeCloner","use: kSortBasketsByBranch");
      fCloneMethod = TTreeCloner::kSortBasketsByBranch;
   } else if (opt.Contains("sortbasketsbyentry")) {
      //::Info("TTreeCloner::TTreeCloner","use: kSortBasketsByEntry");
      fCloneMethod = TTreeCloner::kSortBasketsByEntry;
   } else {
      //::Info("TTreeCloner::TTreeCloner","use: kSortBasketsByOffset");
      fCloneMethod = TTreeCloner::kSortBasketsByOffset;
   }
   if (fToTree) fToStartEntries = fToTree->GetEntries();
}

Bool_t TTreeCloner::Exec()
{
   // Execute the cloning.

   CopyStreamerInfos();
   CopyProcessIds();
   CloseOutWriteBaskets();
   CollectBaskets();
   SortBaskets();
   WriteBaskets();
   CopyMemoryBaskets();

   return kTRUE;
}

TTreeCloner::~TTreeCloner()
{
   // TTreeCloner destructor

   delete [] fBasketBranchNum;
   delete [] fBasketNum;
   delete [] fBasketSeek;
   delete [] fBasketEntry;
   delete [] fBasketIndex;
}

void TTreeCloner::CloseOutWriteBaskets()
{
   // Before we can start adding new basket, we need to flush to
   // disk the partially filled baskets (the WriteBasket)

   for(Int_t i=0; i<fToBranches.GetEntries(); ++i) {
      TBranch *to = (TBranch*)fToBranches.UncheckedAt(i);

      TObjArray *array = to->GetListOfBaskets();
      if (array->GetEntries()) {
         TBasket *basket = to->GetBasket(to->GetWriteBasket());
         if (basket) {
            if (basket->GetNevBuf()) {
               // If the basket already contains entry we need to close it
               // out. (This is because we can only transfer full compressed
               // buffer)

               if (basket->GetBufferRef()->IsReading()) {
                  basket->SetWriteMode();
               }
               to->WriteBasket(basket);
               basket = to->GetBasket(to->GetWriteBasket()); // WriteBasket create an empty basket
            }
            if (basket) {
               basket->DropBuffers();
               to->GetListOfBaskets()->RemoveAt(to->GetWriteBasket());
               delete basket;
            }
         }
      }
   }
}

UInt_t TTreeCloner::CollectBranches(TBranch *from, TBranch *to)
{
   // Fill the array of branches, adding the branch 'from' and 'to',
   // and matching the sub-branches of the 'from' and 'to' branches.
   // Returns the total number of baskets in all the from branch and
   // it sub-branches.

   // Since this is called from the constructor, this can not be a virtual function

   UInt_t numBaskets = 0;
   if (from->InheritsFrom(TBranchClones::Class())) {
      TBranchClones *fromclones = (TBranchClones*)from;
      TBranchClones *toclones = (TBranchClones*)to;
      numBaskets += CollectBranches(fromclones->fBranchCount,toclones->fBranchCount);

   } else if (from->InheritsFrom(TBranchElement::Class())) {
      TBranchElement *fromelem = (TBranchElement*)from;
      TBranchElement *toelem   = (TBranchElement*)to;
      if (fromelem->fMaximum > toelem->fMaximum) toelem->fMaximum = fromelem->fMaximum;
   } else {

      Int_t nb = from->GetListOfLeaves()->GetEntries();
      Int_t fnb= to->GetListOfLeaves()->GetEntries();
      if (nb!=fnb) {
         Error("TTreeCloner::CollectBranches",
            "The export branch and the import branch do not have the same number of leaves (%d vs %d)",
            fnb,nb);
         fIsValid = kFALSE;
         return 0;
      }
      for (Int_t i=0;i<nb;i++)  {
         TLeaf *fromleaf_gen = (TLeaf*)from->GetListOfLeaves()->At(i);
         if (fromleaf_gen->IsA()==TLeafI::Class()) {
            TLeafI *fromleaf = (TLeafI*)from->GetListOfLeaves()->At(i);
            TLeafI *toleaf   = (TLeafI*)to->GetListOfLeaves()->At(i);
            if (fromleaf->GetMaximum() > toleaf->GetMaximum())
               toleaf->SetMaximum( fromleaf->GetMaximum() );
            if (fromleaf->GetMinimum() < toleaf->GetMinimum())
               toleaf->SetMinimum( fromleaf->GetMinimum() );
         } else if (fromleaf_gen->IsA()==TLeafL::Class()) {
            TLeafL *fromleaf = (TLeafL*)from->GetListOfLeaves()->At(i);
            TLeafL *toleaf   = (TLeafL*)to->GetListOfLeaves()->At(i);
            if (fromleaf->GetMaximum() > toleaf->GetMaximum())
               toleaf->SetMaximum( fromleaf->GetMaximum() );
            if (fromleaf->GetMinimum() < toleaf->GetMinimum())
               toleaf->SetMinimum( fromleaf->GetMinimum() );
         }
      }

   }

   fFromBranches.AddLast(from);
   fToBranches.AddLast(to);

   numBaskets += from->GetWriteBasket();
   numBaskets += CollectBranches(from->GetListOfBranches(),to->GetListOfBranches());

   return numBaskets;
}

UInt_t TTreeCloner::CollectBranches(TObjArray *from, TObjArray *to)
{
   // Fill the array of branches, matching the branches of the 'from' and 'to' arrays.
   // Returns the total number of baskets in all the branches.

   // Since this is called from the constructor, this can not be a virtual function

   Int_t nb = from->GetEntries();
   Int_t fnb= to->GetEntries();
   if (nb!=fnb) {
      Error("TTreeCloner::CollectSubBranches",
         "The export branch and the import branch do not have the same number of branches (%d vs %d)",
         fnb,nb);
      fIsValid = kFALSE;
      return 0;
   }

   UInt_t numBasket = 0;
   for (Int_t i=0;i<nb;i++)  {
      numBasket += CollectBranches((TBranch*)from->UncheckedAt(i),(TBranch*)to->UncheckedAt(i));
   }
   return numBasket;
}

UInt_t TTreeCloner::CollectBranches()
{
   // Fill the array of branches, matching the branches of the 'from' and 'to' TTrees
   // Returns the total number of baskets in all the branches.

   // Since this is called from the constructor, this can not be a virtual function

   UInt_t numBasket = CollectBranches(fFromTree->GetListOfBranches(),
                                      fToTree->GetListOfBranches());

   if (fFromTree->GetBranchRef()) {
      fToTree->BranchRef();
      numBasket += CollectBranches(fFromTree->GetBranchRef(),fToTree->GetBranchRef());
   }
   return numBasket;
}

void TTreeCloner::CollectBaskets()
{
   // Collect the information about the on-file basket that need
   // to be copied.

   UInt_t len = fFromBranches.GetEntries();

   for(UInt_t i=0,bi=0; i<len; ++i) {
      TBranch *from = (TBranch*)fFromBranches.UncheckedAt(i);
      for(Int_t b=0; b<from->GetWriteBasket(); ++b,++bi) {
         fBasketBranchNum[bi] = i;
         fBasketNum[bi] = b;
         fBasketSeek[bi] = from->GetBasketSeek(b);
         fBasketEntry[bi] = from->GetBasketEntry()[b];
         fBasketIndex[bi] = bi;
      }
   }
}

void TTreeCloner::CopyStreamerInfos()
{
   // Make sure that all the needed TStreamerInfo are
   // present in the output file

   TFile *fromFile = fFromTree->GetDirectory()->GetFile();
   TFile *toFile = fToTree->GetDirectory()->GetFile();
   TList *l = fromFile->GetStreamerInfoList();
   TIter next(l);
   TStreamerInfo *oldInfo;
   while ( (oldInfo = (TStreamerInfo*)next()) ) {
      TStreamerInfo *curInfo = 0;
      TClass *cl = gROOT->GetClass(oldInfo->GetName());

      // Insure that the TStreamerInfo is loaded
      curInfo = cl->GetStreamerInfo(oldInfo->GetClassVersion());
      if (oldInfo->GetClassVersion()==1) {
         // We may have a Foreign class let's look using the
         // checksum:
         curInfo = cl->FindStreamerInfo(oldInfo->GetCheckSum());
      }
      curInfo->TagFile(toFile);
   }
   delete l;
}

void TTreeCloner::CopyMemoryBaskets()
{
   // Transfer the basket from the input file to the output file

   TBasket *basket = 0;
   for(Int_t i=0; i<fToBranches.GetEntries(); ++i) {
      TBranch *from = (TBranch*)fFromBranches.UncheckedAt( i );
      TBranch *to   = (TBranch*)fToBranches.UncheckedAt( i );

      basket = from->GetListOfBaskets()->GetEntries() ? from->GetBasket(from->GetWriteBasket()) : 0;
      if (basket) {
         basket = (TBasket*)basket->Clone();
         to->AddBasket(*basket, kFALSE, fToStartEntries+from->GetBasketEntry()[from->GetWriteBasket()]);
      }
      // If the branch is a TBranchElement non-terminal 'object' branch, it's basket will contain 0
      // events.
      if (from->GetEntries()!=0 && from->GetWriteBasket()==0 && basket->GetNevBuf()==0) {
         to->SetEntries(to->GetEntries()+from->GetEntries());
      }
   }
}

void TTreeCloner::CopyProcessIds()
{
   // Make sure that all the needed TStreamerInfo are
   // present in the output file

   // NOTE: We actually need to merge the ProcessId somehow :(

   TFile *fromfile = fFromTree->GetDirectory()->GetFile();
   TFile *tofile = fToTree->GetDirectory()->GetFile();

   fPidOffset = tofile->GetNProcessIDs();

   TIter next(fromfile->GetListOfKeys());
   TKey *key;
   TDirectory::TContext cur(gDirectory,fromfile);
   while ((key = (TKey*)next())) {
      if (!strcmp(key->GetClassName(),"TProcessID")) {
         TProcessID *id = (TProcessID*)key->ReadObjectAny(0);

         UShort_t out = TProcessID::WriteProcessID(id,tofile);
         if (out<fPidOffset) {
            Error("CopyProcessIDs","Copied %s from %s might already exist!\n",
                  id->GetName(),fromfile->GetName());
         }
      }
   }
}

void TTreeCloner::SortBaskets()
{
   // Sort the basket according to the user request.

   // Currently this sort __has to__ preserve the order
   // of basket for each individual branch.

   switch (fCloneMethod) {
      case kSortBasketsByBranch:
         // nothing to do, it is already sorted.
         break;
      case kSortBasketsByEntry:
         TMath::Sort( fMaxBaskets, fBasketEntry, fBasketIndex, kFALSE );
         break;
      case kSortBasketsByOffset:
      default:
         TMath::Sort( fMaxBaskets, fBasketSeek, fBasketIndex, kFALSE );
         break;
   }
}

void TTreeCloner::WriteBaskets()
{
   // Transfer the basket from the input file to the output file

   TBasket *basket = new TBasket();
   for(UInt_t j=0; j<fMaxBaskets; ++j) {
      TBranch *from = (TBranch*)fFromBranches.UncheckedAt( fBasketBranchNum[ fBasketIndex[j] ] );
      TBranch *to   = (TBranch*)fToBranches.UncheckedAt( fBasketBranchNum[ fBasketIndex[j] ] );

      TFile *tofile = to->GetFile(0);
      TFile *fromfile = from->GetFile(0);

      Int_t index = fBasketNum[ fBasketIndex[j] ];

      Long64_t pos = from->GetBasketSeek(index);
      if (from->GetBasketBytes()[index] == 0) {
         from->GetBasketBytes()[index] = basket->ReadBasketBytes(pos, fromfile);
      }
      Int_t len = from->GetBasketBytes()[index];
      Long64_t entryInBasket;
      if (index == from->GetWriteBasket()) {
         entryInBasket = from->GetEntries() - from->GetBasketEntry()[index];
      } else {
         entryInBasket = from->GetBasketEntry()[index+1] - from->GetBasketEntry()[index];
      }

      basket->LoadBasketBuffers(pos,len,fromfile);
      basket->IncrementPidOffset(fPidOffset);
      basket->CopyTo(tofile);
      to->AddBasket(*basket,kTRUE,fToStartEntries + from->GetBasketEntry()[index]);

   }
   delete basket;
}
<commit_msg>Insure that the TLeafB have their maximum and minimum properly updated.<commit_after>// @(#)root/tree:$Name:  $:$Id: TTreeCloner.cxx,v 1.10 2006/09/28 17:37:55 pcanal Exp $
// Author: Philippe Canal 07/11/2005

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TTreeCloner                                                          //
//                                                                      //
// Class implementing or helping  the various TTree cloning method      //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TBasket.h"
#include "TBranch.h"
#include "TBranchClones.h"
#include "TBranchElement.h"
#include "TStreamerInfo.h"
#include "TBranchRef.h"
#include "TError.h"
#include "TProcessID.h"
#include "TTree.h"
#include "TTreeCloner.h"
#include "TFile.h"
#include "TLeafB.h"
#include "TLeafI.h"
#include "TLeafL.h"

TTreeCloner::TTreeCloner(TTree *from, TTree *to, Option_t *method) :
   fIsValid(kTRUE),
   fFromTree(from),
   fToTree(to),
   fMethod(method),
   fFromBranches( from ? from->GetListOfLeaves()->GetEntries()+1 : 0),
   fToBranches( to ? from->GetListOfLeaves()->GetEntries()+1 : 0),
   fMaxBaskets(CollectBranches()),
   fBasketBranchNum(new UInt_t[fMaxBaskets]),
   fBasketNum(new UInt_t[fMaxBaskets]),
   fBasketSeek(new Long64_t[fMaxBaskets]),
   fBasketEntry(new Long64_t[fMaxBaskets]),
   fBasketIndex(new Int_t[fMaxBaskets]),
   fCloneMethod(TTreeCloner::kDefault),
   fToStartEntries(0)
{
   // Constructor.  This object would transfer the data from
   // 'from' to 'to' using the method indicated in method.

   TString opt(method);
   opt.ToLower();
   if (opt.Contains("sortbasketsbybranch")) {
      //::Info("TTreeCloner::TTreeCloner","use: kSortBasketsByBranch");
      fCloneMethod = TTreeCloner::kSortBasketsByBranch;
   } else if (opt.Contains("sortbasketsbyentry")) {
      //::Info("TTreeCloner::TTreeCloner","use: kSortBasketsByEntry");
      fCloneMethod = TTreeCloner::kSortBasketsByEntry;
   } else {
      //::Info("TTreeCloner::TTreeCloner","use: kSortBasketsByOffset");
      fCloneMethod = TTreeCloner::kSortBasketsByOffset;
   }
   if (fToTree) fToStartEntries = fToTree->GetEntries();
}

Bool_t TTreeCloner::Exec()
{
   // Execute the cloning.

   CopyStreamerInfos();
   CopyProcessIds();
   CloseOutWriteBaskets();
   CollectBaskets();
   SortBaskets();
   WriteBaskets();
   CopyMemoryBaskets();

   return kTRUE;
}

TTreeCloner::~TTreeCloner()
{
   // TTreeCloner destructor

   delete [] fBasketBranchNum;
   delete [] fBasketNum;
   delete [] fBasketSeek;
   delete [] fBasketEntry;
   delete [] fBasketIndex;
}

void TTreeCloner::CloseOutWriteBaskets()
{
   // Before we can start adding new basket, we need to flush to
   // disk the partially filled baskets (the WriteBasket)

   for(Int_t i=0; i<fToBranches.GetEntries(); ++i) {
      TBranch *to = (TBranch*)fToBranches.UncheckedAt(i);

      TObjArray *array = to->GetListOfBaskets();
      if (array->GetEntries()) {
         TBasket *basket = to->GetBasket(to->GetWriteBasket());
         if (basket) {
            if (basket->GetNevBuf()) {
               // If the basket already contains entry we need to close it
               // out. (This is because we can only transfer full compressed
               // buffer)

               if (basket->GetBufferRef()->IsReading()) {
                  basket->SetWriteMode();
               }
               to->WriteBasket(basket);
               basket = to->GetBasket(to->GetWriteBasket()); // WriteBasket create an empty basket
            }
            if (basket) {
               basket->DropBuffers();
               to->GetListOfBaskets()->RemoveAt(to->GetWriteBasket());
               delete basket;
            }
         }
      }
   }
}

UInt_t TTreeCloner::CollectBranches(TBranch *from, TBranch *to)
{
   // Fill the array of branches, adding the branch 'from' and 'to',
   // and matching the sub-branches of the 'from' and 'to' branches.
   // Returns the total number of baskets in all the from branch and
   // it sub-branches.

   // Since this is called from the constructor, this can not be a virtual function

   UInt_t numBaskets = 0;
   if (from->InheritsFrom(TBranchClones::Class())) {
      TBranchClones *fromclones = (TBranchClones*)from;
      TBranchClones *toclones = (TBranchClones*)to;
      numBaskets += CollectBranches(fromclones->fBranchCount,toclones->fBranchCount);

   } else if (from->InheritsFrom(TBranchElement::Class())) {
      TBranchElement *fromelem = (TBranchElement*)from;
      TBranchElement *toelem   = (TBranchElement*)to;
      if (fromelem->fMaximum > toelem->fMaximum) toelem->fMaximum = fromelem->fMaximum;
   } else {

      Int_t nb = from->GetListOfLeaves()->GetEntries();
      Int_t fnb= to->GetListOfLeaves()->GetEntries();
      if (nb!=fnb) {
         Error("TTreeCloner::CollectBranches",
            "The export branch and the import branch do not have the same number of leaves (%d vs %d)",
            fnb,nb);
         fIsValid = kFALSE;
         return 0;
      }
      for (Int_t i=0;i<nb;i++)  {
         TLeaf *fromleaf_gen = (TLeaf*)from->GetListOfLeaves()->At(i);
         if (fromleaf_gen->IsA()==TLeafI::Class()) {
            TLeafI *fromleaf = (TLeafI*)from->GetListOfLeaves()->At(i);
            TLeafI *toleaf   = (TLeafI*)to->GetListOfLeaves()->At(i);
            if (fromleaf->GetMaximum() > toleaf->GetMaximum())
               toleaf->SetMaximum( fromleaf->GetMaximum() );
            if (fromleaf->GetMinimum() < toleaf->GetMinimum())
               toleaf->SetMinimum( fromleaf->GetMinimum() );
         } else if (fromleaf_gen->IsA()==TLeafL::Class()) {
            TLeafL *fromleaf = (TLeafL*)from->GetListOfLeaves()->At(i);
            TLeafL *toleaf   = (TLeafL*)to->GetListOfLeaves()->At(i);
            if (fromleaf->GetMaximum() > toleaf->GetMaximum())
               toleaf->SetMaximum( fromleaf->GetMaximum() );
            if (fromleaf->GetMinimum() < toleaf->GetMinimum())
               toleaf->SetMinimum( fromleaf->GetMinimum() );
         } else if (fromleaf_gen->IsA()==TLeafB::Class()) {
            TLeafB *fromleaf = (TLeafB*)from->GetListOfLeaves()->At(i);
            TLeafB *toleaf   = (TLeafB*)to->GetListOfLeaves()->At(i);
            if (fromleaf->GetMaximum() > toleaf->GetMaximum())
               toleaf->SetMaximum( fromleaf->GetMaximum() );
            if (fromleaf->GetMinimum() < toleaf->GetMinimum())
               toleaf->SetMinimum( fromleaf->GetMinimum() );
         }
      }

   }

   fFromBranches.AddLast(from);
   fToBranches.AddLast(to);

   numBaskets += from->GetWriteBasket();
   numBaskets += CollectBranches(from->GetListOfBranches(),to->GetListOfBranches());

   return numBaskets;
}

UInt_t TTreeCloner::CollectBranches(TObjArray *from, TObjArray *to)
{
   // Fill the array of branches, matching the branches of the 'from' and 'to' arrays.
   // Returns the total number of baskets in all the branches.

   // Since this is called from the constructor, this can not be a virtual function

   Int_t nb = from->GetEntries();
   Int_t fnb= to->GetEntries();
   if (nb!=fnb) {
      Error("TTreeCloner::CollectSubBranches",
         "The export branch and the import branch do not have the same number of branches (%d vs %d)",
         fnb,nb);
      fIsValid = kFALSE;
      return 0;
   }

   UInt_t numBasket = 0;
   for (Int_t i=0;i<nb;i++)  {
      numBasket += CollectBranches((TBranch*)from->UncheckedAt(i),(TBranch*)to->UncheckedAt(i));
   }
   return numBasket;
}

UInt_t TTreeCloner::CollectBranches()
{
   // Fill the array of branches, matching the branches of the 'from' and 'to' TTrees
   // Returns the total number of baskets in all the branches.

   // Since this is called from the constructor, this can not be a virtual function

   UInt_t numBasket = CollectBranches(fFromTree->GetListOfBranches(),
                                      fToTree->GetListOfBranches());

   if (fFromTree->GetBranchRef()) {
      fToTree->BranchRef();
      numBasket += CollectBranches(fFromTree->GetBranchRef(),fToTree->GetBranchRef());
   }
   return numBasket;
}

void TTreeCloner::CollectBaskets()
{
   // Collect the information about the on-file basket that need
   // to be copied.

   UInt_t len = fFromBranches.GetEntries();

   for(UInt_t i=0,bi=0; i<len; ++i) {
      TBranch *from = (TBranch*)fFromBranches.UncheckedAt(i);
      for(Int_t b=0; b<from->GetWriteBasket(); ++b,++bi) {
         fBasketBranchNum[bi] = i;
         fBasketNum[bi] = b;
         fBasketSeek[bi] = from->GetBasketSeek(b);
         fBasketEntry[bi] = from->GetBasketEntry()[b];
         fBasketIndex[bi] = bi;
      }
   }
}

void TTreeCloner::CopyStreamerInfos()
{
   // Make sure that all the needed TStreamerInfo are
   // present in the output file

   TFile *fromFile = fFromTree->GetDirectory()->GetFile();
   TFile *toFile = fToTree->GetDirectory()->GetFile();
   TList *l = fromFile->GetStreamerInfoList();
   TIter next(l);
   TStreamerInfo *oldInfo;
   while ( (oldInfo = (TStreamerInfo*)next()) ) {
      TStreamerInfo *curInfo = 0;
      TClass *cl = gROOT->GetClass(oldInfo->GetName());

      // Insure that the TStreamerInfo is loaded
      curInfo = cl->GetStreamerInfo(oldInfo->GetClassVersion());
      if (oldInfo->GetClassVersion()==1) {
         // We may have a Foreign class let's look using the
         // checksum:
         curInfo = cl->FindStreamerInfo(oldInfo->GetCheckSum());
      }
      curInfo->TagFile(toFile);
   }
   delete l;
}

void TTreeCloner::CopyMemoryBaskets()
{
   // Transfer the basket from the input file to the output file

   TBasket *basket = 0;
   for(Int_t i=0; i<fToBranches.GetEntries(); ++i) {
      TBranch *from = (TBranch*)fFromBranches.UncheckedAt( i );
      TBranch *to   = (TBranch*)fToBranches.UncheckedAt( i );

      basket = from->GetListOfBaskets()->GetEntries() ? from->GetBasket(from->GetWriteBasket()) : 0;
      if (basket) {
         basket = (TBasket*)basket->Clone();
         to->AddBasket(*basket, kFALSE, fToStartEntries+from->GetBasketEntry()[from->GetWriteBasket()]);
      }
      // If the branch is a TBranchElement non-terminal 'object' branch, it's basket will contain 0
      // events.
      if (from->GetEntries()!=0 && from->GetWriteBasket()==0 && basket->GetNevBuf()==0) {
         to->SetEntries(to->GetEntries()+from->GetEntries());
      }
   }
}

void TTreeCloner::CopyProcessIds()
{
   // Make sure that all the needed TStreamerInfo are
   // present in the output file

   // NOTE: We actually need to merge the ProcessId somehow :(

   TFile *fromfile = fFromTree->GetDirectory()->GetFile();
   TFile *tofile = fToTree->GetDirectory()->GetFile();

   fPidOffset = tofile->GetNProcessIDs();

   TIter next(fromfile->GetListOfKeys());
   TKey *key;
   TDirectory::TContext cur(gDirectory,fromfile);
   while ((key = (TKey*)next())) {
      if (!strcmp(key->GetClassName(),"TProcessID")) {
         TProcessID *id = (TProcessID*)key->ReadObjectAny(0);

         UShort_t out = TProcessID::WriteProcessID(id,tofile);
         if (out<fPidOffset) {
            Error("CopyProcessIDs","Copied %s from %s might already exist!\n",
                  id->GetName(),fromfile->GetName());
         }
      }
   }
}

void TTreeCloner::SortBaskets()
{
   // Sort the basket according to the user request.

   // Currently this sort __has to__ preserve the order
   // of basket for each individual branch.

   switch (fCloneMethod) {
      case kSortBasketsByBranch:
         // nothing to do, it is already sorted.
         break;
      case kSortBasketsByEntry:
         TMath::Sort( fMaxBaskets, fBasketEntry, fBasketIndex, kFALSE );
         break;
      case kSortBasketsByOffset:
      default:
         TMath::Sort( fMaxBaskets, fBasketSeek, fBasketIndex, kFALSE );
         break;
   }
}

void TTreeCloner::WriteBaskets()
{
   // Transfer the basket from the input file to the output file

   TBasket *basket = new TBasket();
   for(UInt_t j=0; j<fMaxBaskets; ++j) {
      TBranch *from = (TBranch*)fFromBranches.UncheckedAt( fBasketBranchNum[ fBasketIndex[j] ] );
      TBranch *to   = (TBranch*)fToBranches.UncheckedAt( fBasketBranchNum[ fBasketIndex[j] ] );

      TFile *tofile = to->GetFile(0);
      TFile *fromfile = from->GetFile(0);

      Int_t index = fBasketNum[ fBasketIndex[j] ];

      Long64_t pos = from->GetBasketSeek(index);
      if (from->GetBasketBytes()[index] == 0) {
         from->GetBasketBytes()[index] = basket->ReadBasketBytes(pos, fromfile);
      }
      Int_t len = from->GetBasketBytes()[index];
      Long64_t entryInBasket;
      if (index == from->GetWriteBasket()) {
         entryInBasket = from->GetEntries() - from->GetBasketEntry()[index];
      } else {
         entryInBasket = from->GetBasketEntry()[index+1] - from->GetBasketEntry()[index];
      }

      basket->LoadBasketBuffers(pos,len,fromfile);
      basket->IncrementPidOffset(fPidOffset);
      basket->CopyTo(tofile);
      to->AddBasket(*basket,kTRUE,fToStartEntries + from->GetBasketEntry()[index]);

   }
   delete basket;
}
<|endoftext|>