<commit_before>/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#if SK_SUPPORT_GPU

#include "gm.h"
#include "SkCanvas.h"
#include "SkColorShader.h"
#include "SkPaint.h"
#include "SkSurface.h"

namespace skiagm {

/*
 * This GM exercises SkCanvas::discard() by creating an offscreen SkSurface and repeatedly
 * discarding it, drawing to it, and then drawing it to the main canvas.
 */
class DiscardGM : public GM {

public:
    DiscardGM() {
    }

    virtual uint32_t onGetFlags() const SK_OVERRIDE { return kGPUOnly_Flag; }

protected:
    virtual SkString onShortName() SK_OVERRIDE {
        return SkString("discard");
    }

    virtual SkISize onISize() SK_OVERRIDE {
        return SkISize::Make(100, 100);
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        GrContext* context = canvas->getGrContext();
        if (NULL == context) {
            return;
        }

        SkISize size = this->getISize();
        size.fWidth /= 10;
        size.fHeight /= 10;
        SkImageInfo info = SkImageInfo::MakeN32Premul(size);
        SkSurface* surface = SkSurface::NewRenderTarget(context, info);

        if (NULL == surface) {
            return;
        }

        canvas->clear(SK_ColorBLACK);

        SkRandom rand;
        for (int x = 0; x < 10; ++x) {
            for (int y = 0; y < 10; ++y) {
              surface->getCanvas()->discard();
              // Make something that isn't too close to the background color, black.
              SkColor color = rand.nextU() | 0xFF404040;
              switch (rand.nextULessThan(3)) {
                  case 0:
                      surface->getCanvas()->drawColor(color);
                      break;
                  case 1:
                      surface->getCanvas()->clear(color);
                      break;
                  case 2:
                      SkColorShader shader(color);
                      SkPaint paint;
                      paint.setShader(&shader);
                      surface->getCanvas()->drawPaint(paint);
                      break;
              }
              surface->draw(canvas, 10*x, 10*y, NULL);
            }
        }

        surface->getCanvas()->discard();
        surface->unref();
    }

private:
    typedef GM INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

DEF_GM( return SkNEW(DiscardGM); )

} // end namespace

#endif
<commit_msg>Fix int->scalar warning on windows<commit_after>/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#if SK_SUPPORT_GPU

#include "gm.h"
#include "SkCanvas.h"
#include "SkColorShader.h"
#include "SkPaint.h"
#include "SkSurface.h"

namespace skiagm {

/*
 * This GM exercises SkCanvas::discard() by creating an offscreen SkSurface and repeatedly
 * discarding it, drawing to it, and then drawing it to the main canvas.
 */
class DiscardGM : public GM {

public:
    DiscardGM() {
    }

    virtual uint32_t onGetFlags() const SK_OVERRIDE { return kGPUOnly_Flag; }

protected:
    virtual SkString onShortName() SK_OVERRIDE {
        return SkString("discard");
    }

    virtual SkISize onISize() SK_OVERRIDE {
        return SkISize::Make(100, 100);
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        GrContext* context = canvas->getGrContext();
        if (NULL == context) {
            return;
        }

        SkISize size = this->getISize();
        size.fWidth /= 10;
        size.fHeight /= 10;
        SkImageInfo info = SkImageInfo::MakeN32Premul(size);
        SkSurface* surface = SkSurface::NewRenderTarget(context, info);

        if (NULL == surface) {
            return;
        }

        canvas->clear(SK_ColorBLACK);

        SkRandom rand;
        for (int x = 0; x < 10; ++x) {
            for (int y = 0; y < 10; ++y) {
              surface->getCanvas()->discard();
              // Make something that isn't too close to the background color, black.
              SkColor color = rand.nextU() | 0xFF404040;
              switch (rand.nextULessThan(3)) {
                  case 0:
                      surface->getCanvas()->drawColor(color);
                      break;
                  case 1:
                      surface->getCanvas()->clear(color);
                      break;
                  case 2:
                      SkColorShader shader(color);
                      SkPaint paint;
                      paint.setShader(&shader);
                      surface->getCanvas()->drawPaint(paint);
                      break;
              }
              surface->draw(canvas, 10.f*x, 10.f*y, NULL);
            }
        }

        surface->getCanvas()->discard();
        surface->unref();
    }

private:
    typedef GM INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

DEF_GM( return SkNEW(DiscardGM); )

} // end namespace

#endif
<|endoftext|>


<commit_before>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2017 Advanced Micro Devices, Inc.
 *
 * 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 <miopen/rnn.hpp>
#include <miopen/errors.hpp>
//#include <miopen/logger.hpp>
#include <miopen/tensor_ops.hpp>

// TODO: Make miopenConvAlgoPerf_t loggable
//inline std::ostream& operator<<(std::ostream& os, miopenConvAlgoPerf_t) { return os; }

extern "C" miopenStatus_t miopenCreateRNNDescriptor(miopenRNNDescriptor_t* rnnDesc)
{
    MIOPEN_LOG_FUNCTION(rnnDesc);
    return miopen::try_([&] { miopen::deref(rnnDesc) = new miopen::RNNDescriptor(); });
}

extern "C" miopenStatus_t miopenInitRNNDescriptor(miopenRNNDescriptor_t rnnDesc,
	miopenRNNMode_t mode,
	int seqLength,
	int layer,
	int bidir)
{

    MIOPEN_LOG_FUNCTION(rnnDesc, mode, seqLength, layer, bidir);
    return miopen::try_([&] {
        miopen::deref(rnnDesc) =
            miopen::RNNDescriptor(mode, seqLength, layer, bidir);
    });
}

extern "C" miopenStatus_t miopenGetRNNDescriptor(miopenRNNDescriptor_t rnnDesc,
                                                         miopenRNNMode_t* mode,
	                                                     int* seqLength,
	                                                     int* layer,
	                                                     int* bidir)
{

	MIOPEN_LOG_FUNCTION(rnnDesc, mode, seqLength, layer, bidir);
    return miopen::try_([&] {
        miopen::deref(mode)       = miopen::deref(rnnDesc).mode;
        miopen::deref(seqLength)      = miopen::deref(rnnDesc).seqLength;
        miopen::deref(layer)      = miopen::deref(rnnDesc).layer;
        miopen::deref(bidir)          = miopen::deref(rnnDesc).bidir;
    });
}

/*
extern "C" miopenStatus_t
miopenGetConvolutionForwardOutputDim(miopenRNNDescriptor_t rnnDesc,
                                     const miopenTensorDescriptor_t inputTensorDesc,
                                     const miopenTensorDescriptor_t filterDesc,
                                     int* n,
                                     int* c,
                                     int* h,
                                     int* w)
{

    MIOPEN_LOG_FUNCTION(rnnDesc, inputTensorDesc, filterDesc, n, c, h, w);
    return miopen::try_([&] {
        miopen::tie_deref(n, c, h, w) = miopen::deref(rnnDesc).GetForwardOutputDim(
            miopen::deref(inputTensorDesc), miopen::deref(filterDesc));
    });
}
*/

extern "C" miopenStatus_t miopenDestroyRNNDescriptor(miopenRNNDescriptor_t rnnDesc)
{
    MIOPEN_LOG_FUNCTION(rnnDesc);
    return miopen::try_([&] { delete rnnDesc; });
}

/*
extern "C" miopenStatus_t
miopenConvolutionForwardGetWorkSpaceSize(miopenHandle_t handle,
                                         const miopenTensorDescriptor_t wDesc,
                                         const miopenTensorDescriptor_t xDesc,
                                         const miopenRNNDescriptor_t rnnDesc,
                                         const miopenTensorDescriptor_t yDesc,
                                         size_t* workSpaceSize)
{

    MIOPEN_LOG_FUNCTION(wDesc, yDesc, rnnDesc, workSpaceSize);
    miopen::try_([&] {
        miopen::deref(workSpaceSize) =
            miopen::deref(rnnDesc).ForwardGetWorkSpaceSize(miopen::deref(handle),
                                                            miopen::deref(wDesc),
                                                            miopen::deref(xDesc),
                                                            miopen::deref(yDesc));
    });

    return (miopenStatusSuccess);
}

extern "C" miopenStatus_t
miopenFindConvolutionForwardAlgorithm(miopenHandle_t handle,
                                      const miopenTensorDescriptor_t xDesc,
                                      const void* x,
                                      const miopenTensorDescriptor_t wDesc,
                                      const void* w,
                                      const miopenRNNDescriptor_t rnnDesc,
                                      const miopenTensorDescriptor_t yDesc,
                                      void* y,
                                      const int requestAlgoCount,
                                      int* returnedAlgoCount,
                                      miopenConvAlgoPerf_t* perfResults,
                                      void* workSpace,
                                      size_t workSpaceSize,
                                      bool exhaustiveSearch)
{

    MIOPEN_LOG_FUNCTION(xDesc,
                        x,
                        wDesc,
                        w,
                        rnnDesc,
                        yDesc,
                        y,
                        requestAlgoCount,
                        returnedAlgoCount,
                        perfResults,
                        workSpace,
                        workSpaceSize,
                        exhaustiveSearch);
    return miopen::try_([&] {
        miopen::deref(rnnDesc).FindConvFwdAlgorithm(miopen::deref(handle),
                                                     miopen::deref(xDesc),
                                                     DataCast(x),
                                                     miopen::deref(wDesc),
                                                     DataCast(w),
                                                     miopen::deref(yDesc),
                                                     DataCast(y),
                                                     requestAlgoCount,
                                                     returnedAlgoCount,
                                                     perfResults,
                                                     DataCast(workSpace),
                                                     workSpaceSize,
                                                     exhaustiveSearch);
    });
}

extern "C" miopenStatus_t miopenConvolutionForward(miopenHandle_t handle,
                                                   const void* alpha,
                                                   const miopenTensorDescriptor_t xDesc,
                                                   const void* x,
                                                   const miopenTensorDescriptor_t wDesc,
                                                   const void* w,
                                                   const miopenRNNDescriptor_t rnnDesc,
                                                   miopenConvFwdAlgorithm_t algo,
                                                   const void* beta,
                                                   const miopenTensorDescriptor_t yDesc,
                                                   void* y,
                                                   void* workSpace,
                                                   size_t workSpaceSize)
{

    MIOPEN_LOG_FUNCTION(
        alpha, xDesc, x, wDesc, w, rnnDesc, algo, beta, yDesc, y, workSpace, workSpaceSize);
    return miopen::try_([&] {
        miopen::deref(rnnDesc).ConvolutionForward(miopen::deref(handle),
                                                   alpha,
                                                   miopen::deref(xDesc),
                                                   DataCast(x),
                                                   miopen::deref(wDesc),
                                                   DataCast(w),
                                                   algo,
                                                   beta,
                                                   miopen::deref(yDesc),
                                                   DataCast(y),
                                                   DataCast(workSpace),
                                                   workSpaceSize);
    });
}

extern "C" miopenStatus_t miopenConvolutionForwardBias(miopenHandle_t handle,
                                                       const void* alpha,
                                                       const miopenTensorDescriptor_t bDesc,
                                                       const void* b,
                                                       const void* beta,
                                                       const miopenTensorDescriptor_t yDesc,
                                                       void* y)
{

    MIOPEN_LOG_FUNCTION(alpha, bDesc, b, beta, yDesc, y);
    return miopen::try_([&] {

        return OpTensor(miopen::deref(handle),
                        miopenTensorOpAdd,
                        alpha,
                        miopen::deref(yDesc),
                        DataCast(y),
                        alpha,
                        miopen::deref(bDesc),
                        DataCast(b),
                        beta,
                        miopen::deref(yDesc),
                        DataCast(y));
    });
}

extern "C" miopenStatus_t
miopenFindConvolutionBackwardDataAlgorithm(miopenHandle_t handle,
                                           const miopenTensorDescriptor_t dyDesc,
                                           const void* dy,
                                           const miopenTensorDescriptor_t wDesc,
                                           const void* w,
                                           const miopenRNNDescriptor_t rnnDesc,
                                           const miopenTensorDescriptor_t dxDesc,
                                           const void* dx,
                                           const int requestAlgoCount,
                                           int* returnedAlgoCount,
                                           miopenConvAlgoPerf_t* perfResults,
                                           void* workSpace,
                                           size_t workSpaceSize,
                                           bool exhaustiveSearch)
{

    MIOPEN_LOG_FUNCTION(dyDesc,
                        dy,
                        wDesc,
                        w,
                        rnnDesc,
                        dxDesc,
                        dx,
                        requestAlgoCount,
                        returnedAlgoCount,
                        perfResults,
                        workSpace,
                        workSpaceSize,
                        exhaustiveSearch);
    return miopen::try_([&] {
        miopen::deref(rnnDesc).FindConvBwdDataAlgorithm(miopen::deref(handle),
                                                         miopen::deref(dyDesc),
                                                         DataCast(dy),
                                                         miopen::deref(wDesc),
                                                         DataCast(w),
                                                         miopen::deref(dxDesc),
                                                         DataCast(dx),
                                                         requestAlgoCount,
                                                         returnedAlgoCount,
                                                         perfResults,
                                                         DataCast(workSpace),
                                                         workSpaceSize,
                                                         exhaustiveSearch);
    });
}

extern "C" miopenStatus_t
miopenConvolutionBackwardData(miopenHandle_t handle,
                              const void* alpha,
                              const miopenTensorDescriptor_t dyDesc,
                              const void* dy,
                              const miopenTensorDescriptor_t wDesc,
                              const void* w,
                              const miopenRNNDescriptor_t rnnDesc,
                              miopenConvBwdDataAlgorithm_t algo,
                              const void* beta,
                              const miopenTensorDescriptor_t dxDesc,
                              void* dx,
                              void* workSpace,
                              size_t workSpaceSize)
{

    MIOPEN_LOG_FUNCTION(
        alpha, dyDesc, dy, wDesc, w, rnnDesc, algo, beta, dxDesc, dx, workSpace, workSpaceSize);
    return miopen::try_([&] {
        miopen::deref(rnnDesc).ConvolutionBackwardData(miopen::deref(handle),
                                                        alpha,
                                                        miopen::deref(dyDesc),
                                                        DataCast(dy),
                                                        miopen::deref(wDesc),
                                                        DataCast(w),
                                                        algo,
                                                        beta,
                                                        miopen::deref(dxDesc),
                                                        DataCast(dx),
                                                        DataCast(workSpace),
                                                        workSpaceSize);
    });
}

extern "C" miopenStatus_t
miopenConvolutionBackwardDataGetWorkSpaceSize(miopenHandle_t handle,
                                              const miopenTensorDescriptor_t dyDesc,
                                              const miopenTensorDescriptor_t wDesc,
                                              const miopenRNNDescriptor_t rnnDesc,
                                              const miopenTensorDescriptor_t dxDesc,
                                              size_t* workSpaceSize)
{

    MIOPEN_LOG_FUNCTION(dyDesc, wDesc, rnnDesc, dxDesc, workSpaceSize);
    return miopen::try_([&] {
        miopen::deref(workSpaceSize) =
            miopen::deref(rnnDesc).BackwardDataGetWorkSpaceSize(miopen::deref(handle),
                                                                 miopen::deref(wDesc),
                                                                 miopen::deref(dyDesc),
                                                                 miopen::deref(dxDesc));
    });
}

extern "C" miopenStatus_t
miopenConvolutionBackwardWeightsGetWorkSpaceSize(miopenHandle_t handle,
                                                 const miopenTensorDescriptor_t dyDesc,
                                                 const miopenTensorDescriptor_t xDesc,
                                                 const miopenRNNDescriptor_t rnnDesc,
                                                 const miopenTensorDescriptor_t dwDesc,
                                                 size_t* workSpaceSize)
{

    MIOPEN_LOG_FUNCTION(dyDesc, xDesc, rnnDesc, dwDesc, workSpaceSize);
    return miopen::try_([&] {
        miopen::deref(workSpaceSize) =
            miopen::deref(rnnDesc).ConvolutionBackwardWeightsGetWorkSpaceSize(
                miopen::deref(handle),
                miopen::deref(dyDesc),
                miopen::deref(xDesc),
                miopen::deref(dwDesc));
    });
}

extern "C" miopenStatus_t
miopenFindConvolutionBackwardWeightsAlgorithm(miopenHandle_t handle,
                                              const miopenTensorDescriptor_t dyDesc,
                                              const void* dy,
                                              const miopenTensorDescriptor_t xDesc,
                                              const void* x,
                                              const miopenRNNDescriptor_t rnnDesc,
                                              const miopenTensorDescriptor_t dwDesc,
                                              void* dw,
                                              const int requestAlgoCount,
                                              int* returnedAlgoCount,
                                              miopenConvAlgoPerf_t* perfResults,
                                              void* workSpace,
                                              size_t workSpaceSize,
                                              bool exhaustiveSearch)
{

    MIOPEN_LOG_FUNCTION(dyDesc,
                        dy,
                        xDesc,
                        x,
                        rnnDesc,
                        dwDesc,
                        dw,
                        requestAlgoCount,
                        returnedAlgoCount,
                        perfResults,
                        workSpace,
                        workSpaceSize,
                        exhaustiveSearch);
    return miopen::try_([&] {
        miopen::deref(rnnDesc).FindConvBwdWeightsAlgorithm(miopen::deref(handle),
                                                            miopen::deref(dyDesc),
                                                            DataCast(dy),
                                                            miopen::deref(xDesc),
                                                            DataCast(x),
                                                            miopen::deref(dwDesc),
                                                            DataCast(dw),
                                                            requestAlgoCount,
                                                            returnedAlgoCount,
                                                            perfResults,
                                                            DataCast(workSpace),
                                                            workSpaceSize,
                                                            exhaustiveSearch);
    });
}

extern "C" miopenStatus_t
miopenConvolutionBackwardWeights(miopenHandle_t handle,
                                 const void* alpha,
                                 const miopenTensorDescriptor_t dyDesc,
                                 const void* dy,
                                 const miopenTensorDescriptor_t xDesc,
                                 const void* x,
                                 const miopenRNNDescriptor_t rnnDesc,
                                 miopenConvBwdWeightsAlgorithm_t algo,
                                 const void* beta,
                                 const miopenTensorDescriptor_t dwDesc,
                                 void* dw,
                                 void* workSpace,
                                 size_t workSpaceSize)
{

    MIOPEN_LOG_FUNCTION(
        alpha, dyDesc, dy, xDesc, x, rnnDesc, algo, beta, dwDesc, dw, workSpace, workSpaceSize);
    return miopen::try_([&] {
        miopen::deref(rnnDesc).ConvolutionBackwardWeights(miopen::deref(handle),
                                                           alpha,
                                                           miopen::deref(dyDesc),
                                                           DataCast(dy),
                                                           miopen::deref(xDesc),
                                                           DataCast(x),
                                                           algo,
                                                           beta,
                                                           miopen::deref(dwDesc),
                                                           DataCast(dw),
                                                           DataCast(workSpace),
                                                           workSpaceSize);
    });
}

extern "C" miopenStatus_t miopenConvolutionBackwardBias(miopenHandle_t handle,
                                                        const void* alpha,
                                                        const miopenTensorDescriptor_t dyDesc,
                                                        const void* dy,
                                                        const void* beta,
                                                        const miopenTensorDescriptor_t dbDesc,
                                                        void* db)
{
    return miopen::try_([&] {
        ConvolutionBackwardBias(miopen::deref(handle),
                                alpha,
                                miopen::deref(dyDesc),
                                DataCast(dy),
                                beta,
                                miopen::deref(dbDesc),
                                DataCast(db));
    });
}
*/<commit_msg>debug ..<commit_after>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2017 Advanced Micro Devices, Inc.
 *
 * 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 <miopen/rnn.hpp>
#include <miopen/errors.hpp>
#include <miopen/logger.hpp>
#include <miopen/tensor_ops.hpp>

// TODO: Make miopenConvAlgoPerf_t loggable
inline std::ostream& operator<<(std::ostream& os, miopenConvAlgoPerf_t) { return os; }

extern "C" miopenStatus_t miopenCreateRNNDescriptor(miopenRNNDescriptor_t* rnnDesc)
{
    MIOPEN_LOG_FUNCTION(rnnDesc);
    return miopen::try_([&] { miopen::deref(rnnDesc) = new miopen::RNNDescriptor(); });
}

extern "C" miopenStatus_t miopenInitRNNDescriptor(miopenRNNDescriptor_t rnnDesc,
	miopenRNNMode_t mode,
	int seqLength,
	int layer,
	int bidir)
{

    MIOPEN_LOG_FUNCTION(rnnDesc, mode, seqLength, layer, bidir);
    return miopen::try_([&] {
        miopen::deref(rnnDesc) =
            miopen::RNNDescriptor(mode, seqLength, layer, bidir);
    });
}

extern "C" miopenStatus_t miopenGetRNNDescriptor(miopenRNNDescriptor_t rnnDesc,
                                                         miopenRNNMode_t* mode,
	                                                     int* seqLength,
	                                                     int* layer,
	                                                     int* bidir)
{

	MIOPEN_LOG_FUNCTION(rnnDesc, mode, seqLength, layer, bidir);
    return miopen::try_([&] {
        miopen::deref(mode)       = miopen::deref(rnnDesc).mode;
        miopen::deref(seqLength)      = miopen::deref(rnnDesc).seqLength;
        miopen::deref(layer)      = miopen::deref(rnnDesc).layer;
        miopen::deref(bidir)          = miopen::deref(rnnDesc).bidir;
    });
}

/*
extern "C" miopenStatus_t
miopenGetConvolutionForwardOutputDim(miopenRNNDescriptor_t rnnDesc,
                                     const miopenTensorDescriptor_t inputTensorDesc,
                                     const miopenTensorDescriptor_t filterDesc,
                                     int* n,
                                     int* c,
                                     int* h,
                                     int* w)
{

    MIOPEN_LOG_FUNCTION(rnnDesc, inputTensorDesc, filterDesc, n, c, h, w);
    return miopen::try_([&] {
        miopen::tie_deref(n, c, h, w) = miopen::deref(rnnDesc).GetForwardOutputDim(
            miopen::deref(inputTensorDesc), miopen::deref(filterDesc));
    });
}
*/

extern "C" miopenStatus_t miopenDestroyRNNDescriptor(miopenRNNDescriptor_t rnnDesc)
{
    MIOPEN_LOG_FUNCTION(rnnDesc);
    return miopen::try_([&] { delete rnnDesc; });
}

/*
extern "C" miopenStatus_t
miopenConvolutionForwardGetWorkSpaceSize(miopenHandle_t handle,
                                         const miopenTensorDescriptor_t wDesc,
                                         const miopenTensorDescriptor_t xDesc,
                                         const miopenRNNDescriptor_t rnnDesc,
                                         const miopenTensorDescriptor_t yDesc,
                                         size_t* workSpaceSize)
{

    MIOPEN_LOG_FUNCTION(wDesc, yDesc, rnnDesc, workSpaceSize);
    miopen::try_([&] {
        miopen::deref(workSpaceSize) =
            miopen::deref(rnnDesc).ForwardGetWorkSpaceSize(miopen::deref(handle),
                                                            miopen::deref(wDesc),
                                                            miopen::deref(xDesc),
                                                            miopen::deref(yDesc));
    });

    return (miopenStatusSuccess);
}

extern "C" miopenStatus_t
miopenFindConvolutionForwardAlgorithm(miopenHandle_t handle,
                                      const miopenTensorDescriptor_t xDesc,
                                      const void* x,
                                      const miopenTensorDescriptor_t wDesc,
                                      const void* w,
                                      const miopenRNNDescriptor_t rnnDesc,
                                      const miopenTensorDescriptor_t yDesc,
                                      void* y,
                                      const int requestAlgoCount,
                                      int* returnedAlgoCount,
                                      miopenConvAlgoPerf_t* perfResults,
                                      void* workSpace,
                                      size_t workSpaceSize,
                                      bool exhaustiveSearch)
{

    MIOPEN_LOG_FUNCTION(xDesc,
                        x,
                        wDesc,
                        w,
                        rnnDesc,
                        yDesc,
                        y,
                        requestAlgoCount,
                        returnedAlgoCount,
                        perfResults,
                        workSpace,
                        workSpaceSize,
                        exhaustiveSearch);
    return miopen::try_([&] {
        miopen::deref(rnnDesc).FindConvFwdAlgorithm(miopen::deref(handle),
                                                     miopen::deref(xDesc),
                                                     DataCast(x),
                                                     miopen::deref(wDesc),
                                                     DataCast(w),
                                                     miopen::deref(yDesc),
                                                     DataCast(y),
                                                     requestAlgoCount,
                                                     returnedAlgoCount,
                                                     perfResults,
                                                     DataCast(workSpace),
                                                     workSpaceSize,
                                                     exhaustiveSearch);
    });
}

extern "C" miopenStatus_t miopenConvolutionForward(miopenHandle_t handle,
                                                   const void* alpha,
                                                   const miopenTensorDescriptor_t xDesc,
                                                   const void* x,
                                                   const miopenTensorDescriptor_t wDesc,
                                                   const void* w,
                                                   const miopenRNNDescriptor_t rnnDesc,
                                                   miopenConvFwdAlgorithm_t algo,
                                                   const void* beta,
                                                   const miopenTensorDescriptor_t yDesc,
                                                   void* y,
                                                   void* workSpace,
                                                   size_t workSpaceSize)
{

    MIOPEN_LOG_FUNCTION(
        alpha, xDesc, x, wDesc, w, rnnDesc, algo, beta, yDesc, y, workSpace, workSpaceSize);
    return miopen::try_([&] {
        miopen::deref(rnnDesc).ConvolutionForward(miopen::deref(handle),
                                                   alpha,
                                                   miopen::deref(xDesc),
                                                   DataCast(x),
                                                   miopen::deref(wDesc),
                                                   DataCast(w),
                                                   algo,
                                                   beta,
                                                   miopen::deref(yDesc),
                                                   DataCast(y),
                                                   DataCast(workSpace),
                                                   workSpaceSize);
    });
}

extern "C" miopenStatus_t miopenConvolutionForwardBias(miopenHandle_t handle,
                                                       const void* alpha,
                                                       const miopenTensorDescriptor_t bDesc,
                                                       const void* b,
                                                       const void* beta,
                                                       const miopenTensorDescriptor_t yDesc,
                                                       void* y)
{

    MIOPEN_LOG_FUNCTION(alpha, bDesc, b, beta, yDesc, y);
    return miopen::try_([&] {

        return OpTensor(miopen::deref(handle),
                        miopenTensorOpAdd,
                        alpha,
                        miopen::deref(yDesc),
                        DataCast(y),
                        alpha,
                        miopen::deref(bDesc),
                        DataCast(b),
                        beta,
                        miopen::deref(yDesc),
                        DataCast(y));
    });
}

extern "C" miopenStatus_t
miopenFindConvolutionBackwardDataAlgorithm(miopenHandle_t handle,
                                           const miopenTensorDescriptor_t dyDesc,
                                           const void* dy,
                                           const miopenTensorDescriptor_t wDesc,
                                           const void* w,
                                           const miopenRNNDescriptor_t rnnDesc,
                                           const miopenTensorDescriptor_t dxDesc,
                                           const void* dx,
                                           const int requestAlgoCount,
                                           int* returnedAlgoCount,
                                           miopenConvAlgoPerf_t* perfResults,
                                           void* workSpace,
                                           size_t workSpaceSize,
                                           bool exhaustiveSearch)
{

    MIOPEN_LOG_FUNCTION(dyDesc,
                        dy,
                        wDesc,
                        w,
                        rnnDesc,
                        dxDesc,
                        dx,
                        requestAlgoCount,
                        returnedAlgoCount,
                        perfResults,
                        workSpace,
                        workSpaceSize,
                        exhaustiveSearch);
    return miopen::try_([&] {
        miopen::deref(rnnDesc).FindConvBwdDataAlgorithm(miopen::deref(handle),
                                                         miopen::deref(dyDesc),
                                                         DataCast(dy),
                                                         miopen::deref(wDesc),
                                                         DataCast(w),
                                                         miopen::deref(dxDesc),
                                                         DataCast(dx),
                                                         requestAlgoCount,
                                                         returnedAlgoCount,
                                                         perfResults,
                                                         DataCast(workSpace),
                                                         workSpaceSize,
                                                         exhaustiveSearch);
    });
}

extern "C" miopenStatus_t
miopenConvolutionBackwardData(miopenHandle_t handle,
                              const void* alpha,
                              const miopenTensorDescriptor_t dyDesc,
                              const void* dy,
                              const miopenTensorDescriptor_t wDesc,
                              const void* w,
                              const miopenRNNDescriptor_t rnnDesc,
                              miopenConvBwdDataAlgorithm_t algo,
                              const void* beta,
                              const miopenTensorDescriptor_t dxDesc,
                              void* dx,
                              void* workSpace,
                              size_t workSpaceSize)
{

    MIOPEN_LOG_FUNCTION(
        alpha, dyDesc, dy, wDesc, w, rnnDesc, algo, beta, dxDesc, dx, workSpace, workSpaceSize);
    return miopen::try_([&] {
        miopen::deref(rnnDesc).ConvolutionBackwardData(miopen::deref(handle),
                                                        alpha,
                                                        miopen::deref(dyDesc),
                                                        DataCast(dy),
                                                        miopen::deref(wDesc),
                                                        DataCast(w),
                                                        algo,
                                                        beta,
                                                        miopen::deref(dxDesc),
                                                        DataCast(dx),
                                                        DataCast(workSpace),
                                                        workSpaceSize);
    });
}

extern "C" miopenStatus_t
miopenConvolutionBackwardDataGetWorkSpaceSize(miopenHandle_t handle,
                                              const miopenTensorDescriptor_t dyDesc,
                                              const miopenTensorDescriptor_t wDesc,
                                              const miopenRNNDescriptor_t rnnDesc,
                                              const miopenTensorDescriptor_t dxDesc,
                                              size_t* workSpaceSize)
{

    MIOPEN_LOG_FUNCTION(dyDesc, wDesc, rnnDesc, dxDesc, workSpaceSize);
    return miopen::try_([&] {
        miopen::deref(workSpaceSize) =
            miopen::deref(rnnDesc).BackwardDataGetWorkSpaceSize(miopen::deref(handle),
                                                                 miopen::deref(wDesc),
                                                                 miopen::deref(dyDesc),
                                                                 miopen::deref(dxDesc));
    });
}

extern "C" miopenStatus_t
miopenConvolutionBackwardWeightsGetWorkSpaceSize(miopenHandle_t handle,
                                                 const miopenTensorDescriptor_t dyDesc,
                                                 const miopenTensorDescriptor_t xDesc,
                                                 const miopenRNNDescriptor_t rnnDesc,
                                                 const miopenTensorDescriptor_t dwDesc,
                                                 size_t* workSpaceSize)
{

    MIOPEN_LOG_FUNCTION(dyDesc, xDesc, rnnDesc, dwDesc, workSpaceSize);
    return miopen::try_([&] {
        miopen::deref(workSpaceSize) =
            miopen::deref(rnnDesc).ConvolutionBackwardWeightsGetWorkSpaceSize(
                miopen::deref(handle),
                miopen::deref(dyDesc),
                miopen::deref(xDesc),
                miopen::deref(dwDesc));
    });
}

extern "C" miopenStatus_t
miopenFindConvolutionBackwardWeightsAlgorithm(miopenHandle_t handle,
                                              const miopenTensorDescriptor_t dyDesc,
                                              const void* dy,
                                              const miopenTensorDescriptor_t xDesc,
                                              const void* x,
                                              const miopenRNNDescriptor_t rnnDesc,
                                              const miopenTensorDescriptor_t dwDesc,
                                              void* dw,
                                              const int requestAlgoCount,
                                              int* returnedAlgoCount,
                                              miopenConvAlgoPerf_t* perfResults,
                                              void* workSpace,
                                              size_t workSpaceSize,
                                              bool exhaustiveSearch)
{

    MIOPEN_LOG_FUNCTION(dyDesc,
                        dy,
                        xDesc,
                        x,
                        rnnDesc,
                        dwDesc,
                        dw,
                        requestAlgoCount,
                        returnedAlgoCount,
                        perfResults,
                        workSpace,
                        workSpaceSize,
                        exhaustiveSearch);
    return miopen::try_([&] {
        miopen::deref(rnnDesc).FindConvBwdWeightsAlgorithm(miopen::deref(handle),
                                                            miopen::deref(dyDesc),
                                                            DataCast(dy),
                                                            miopen::deref(xDesc),
                                                            DataCast(x),
                                                            miopen::deref(dwDesc),
                                                            DataCast(dw),
                                                            requestAlgoCount,
                                                            returnedAlgoCount,
                                                            perfResults,
                                                            DataCast(workSpace),
                                                            workSpaceSize,
                                                            exhaustiveSearch);
    });
}

extern "C" miopenStatus_t
miopenConvolutionBackwardWeights(miopenHandle_t handle,
                                 const void* alpha,
                                 const miopenTensorDescriptor_t dyDesc,
                                 const void* dy,
                                 const miopenTensorDescriptor_t xDesc,
                                 const void* x,
                                 const miopenRNNDescriptor_t rnnDesc,
                                 miopenConvBwdWeightsAlgorithm_t algo,
                                 const void* beta,
                                 const miopenTensorDescriptor_t dwDesc,
                                 void* dw,
                                 void* workSpace,
                                 size_t workSpaceSize)
{

    MIOPEN_LOG_FUNCTION(
        alpha, dyDesc, dy, xDesc, x, rnnDesc, algo, beta, dwDesc, dw, workSpace, workSpaceSize);
    return miopen::try_([&] {
        miopen::deref(rnnDesc).ConvolutionBackwardWeights(miopen::deref(handle),
                                                           alpha,
                                                           miopen::deref(dyDesc),
                                                           DataCast(dy),
                                                           miopen::deref(xDesc),
                                                           DataCast(x),
                                                           algo,
                                                           beta,
                                                           miopen::deref(dwDesc),
                                                           DataCast(dw),
                                                           DataCast(workSpace),
                                                           workSpaceSize);
    });
}

extern "C" miopenStatus_t miopenConvolutionBackwardBias(miopenHandle_t handle,
                                                        const void* alpha,
                                                        const miopenTensorDescriptor_t dyDesc,
                                                        const void* dy,
                                                        const void* beta,
                                                        const miopenTensorDescriptor_t dbDesc,
                                                        void* db)
{
    return miopen::try_([&] {
        ConvolutionBackwardBias(miopen::deref(handle),
                                alpha,
                                miopen::deref(dyDesc),
                                DataCast(dy),
                                beta,
                                miopen::deref(dbDesc),
                                DataCast(db));
    });
}
*/<|endoftext|>


<commit_before>/*
 * Session management.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "session.hxx"
#include "cookie_jar.hxx"
#include "shm/dpool.hxx"
#include "shm/dbuffer.hxx"
#include "expiry.h"
#include "crash.hxx"
#include "expiry.h"

#include <daemon/log.h>

#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <event.h>

#define SESSION_TTL_NEW 120

inline
Session::Session(struct dpool *_pool)
    :pool(_pool),
     expires(expiry_touch(SESSION_TTL_NEW)),
     counter(1),
     is_new(true),
     cookie_sent(false), cookie_received(false),
     realm(nullptr),
     translate(nullptr),
     user(nullptr),
     user_expires(0),
     language(nullptr),
     cookies(cookie_jar_new(*_pool))
{
    lock_init(&lock);
}

inline
Session::Session(struct dpool *_pool, const Session &src)
    :pool(_pool),
     id(src.id),
     expires(src.expires),
     counter(1),
     is_new(src.is_new),
     cookie_sent(src.cookie_sent), cookie_received(src.cookie_received),
     realm(d_strdup_checked(pool, src.realm)),
     translate(DupBuffer(pool, src.translate)),
     user(d_strdup_checked(pool, src.user)),
     user_expires(0),
     language(d_strdup_checked(pool, src.language)),
     cookies(src.cookies->Dup(*pool))
{
    lock_init(&lock);
}

inline
Session::~Session()
{
    lock_destroy(&lock);
}

Session *
session_allocate(struct dpool *pool)
{
    return NewFromPool<Session>(pool, pool);
}

void
session_destroy(Session *session)
{
    DeleteDestroyPool(*session->pool, session);
}

/**
 * Calculates the score for purging the session: higher score means
 * more likely to be purged.
 */
unsigned
session_purge_score(const Session *session)
{
    if (session->is_new)
        return 1000;

    if (!session->cookie_received)
        return 50;

    if (session->user == nullptr)
        return 20;

    return 1;
}

void
session_clear_translate(Session *session)
{
    assert(crash_in_unsafe());
    assert(session != nullptr);

    if (!session->translate.IsEmpty()) {
        d_free(session->pool, session->translate.data);
        session->translate = nullptr;
    }
}

void
session_clear_user(Session *session)
{
    assert(crash_in_unsafe());
    assert(session != nullptr);

    if (session->user != nullptr) {
        d_free(session->pool, session->user);
        session->user = nullptr;
    }
}

void
session_clear_language(Session *session)
{
    assert(crash_in_unsafe());
    assert(session != nullptr);

    if (session->language != nullptr) {
        d_free(session->pool, session->language);
        session->language = nullptr;
    }
}

bool
session_set_translate(Session *session, ConstBuffer<void> translate)
{
    assert(crash_in_unsafe());
    assert(session != nullptr);
    assert(!translate.IsNull());

    if (!session->translate.IsNull() &&
        session->translate.size == translate.size &&
        memcmp(session->translate.data, translate.data, translate.size) == 0)
        /* same value as before: no-op */
        return true;

    session_clear_translate(session);

    session->translate = DupBuffer(session->pool, translate);
    return !session->translate.IsNull();
}

bool
session_set_user(Session *session, const char *user, unsigned max_age)
{
    assert(crash_in_unsafe());
    assert(session != nullptr);
    assert(user != nullptr);

    if (session->user == nullptr || strcmp(session->user, user) != 0) {
        session_clear_user(session);

        session->user = d_strdup(session->pool, user);
        if (session->user == nullptr)
            return false;
    }

    if (max_age == (unsigned)-1)
        /* never expires */
        session->user_expires = 0;
    else if (max_age == 0)
        /* expires immediately, use only once */
        session->user_expires = 1;
    else
        session->user_expires = expiry_touch(max_age);

    return true;
}

bool
session_set_language(Session *session, const char *language)
{
    assert(crash_in_unsafe());
    assert(session != nullptr);
    assert(language != nullptr);

    if (session->language != nullptr && strcmp(session->language, language) == 0)
        /* same value as before: no-op */
        return true;

    session_clear_language(session);

    session->language = d_strdup(session->pool, language);
    return session->language != nullptr;
}

static WidgetSession::Set
widget_session_map_dup(struct dpool *pool, const WidgetSession::Set &src,
                       Session *session, WidgetSession *parent);

gcc_malloc
static WidgetSession *
widget_session_dup(struct dpool *pool, const WidgetSession *src,
                   Session *session)
{
    assert(crash_in_unsafe());
    assert(src != nullptr);
    assert(src->id != nullptr);

    auto *dest = NewFromPool<WidgetSession>(pool);
    if (dest == nullptr)
        return nullptr;

    dest->id = d_strdup(pool, src->id);
    if (dest->id == nullptr)
        return nullptr;

    dest->children = widget_session_map_dup(pool, src->children,
                                            session, dest);

    if (src->path_info != nullptr) {
        dest->path_info = d_strdup(pool, src->path_info);
        if (dest->path_info == nullptr)
            return nullptr;
    } else
        dest->path_info = nullptr;

    if (src->query_string != nullptr) {
        dest->query_string = d_strdup(pool, src->query_string);
        if (dest->query_string == nullptr)
            return nullptr;
    } else
        dest->query_string = nullptr;

    return dest;
}

static WidgetSession::Set
widget_session_map_dup(struct dpool *pool, const WidgetSession::Set &src,
                       Session *session, WidgetSession *parent)
{
    assert(crash_in_unsafe());

    WidgetSession::Set dest;

    for (const auto &src_ws : src) {
        WidgetSession *dest_ws = widget_session_dup(pool, &src_ws, session);
        if (dest_ws == nullptr)
            break;

        dest_ws->parent = parent;
        dest_ws->session = session;

        dest.insert(*dest_ws);
    }

    return std::move(dest);
}

Session *
session_dup(struct dpool *pool, const Session *src)
{
    assert(crash_in_unsafe());

    auto *dest = NewFromPool<Session>(pool, pool, *src);
    if (dest == nullptr)
        return nullptr;

    dest->widgets = widget_session_map_dup(pool, src->widgets, dest, nullptr);
    return dest;
}

WidgetSession *
widget_session_allocate(Session *session)
{
    auto *ws = NewFromPool<WidgetSession>(session->pool);
    if (ws == nullptr)
        return nullptr;

    ws->session = session;
    return ws;
}

static WidgetSession *
hashmap_r_get_widget_session(Session *session, WidgetSession::Set &set,
                             const char *id, bool create)
{
    assert(crash_in_unsafe());
    assert(session != nullptr);
    assert(lock_is_locked(&session->lock));
    assert(id != nullptr);

    auto i = set.find(id, WidgetSession::Compare());
    if (i != set.end())
        return &*i;

    if (!create)
        return nullptr;

    auto *ws = widget_session_allocate(session);
    if (ws == nullptr)
        return nullptr;

    ws->parent = nullptr;
    ws->id = d_strdup(session->pool, id);
    if (ws->id == nullptr) {
        DeleteFromPool(session->pool, ws);
        return nullptr;
    }

    ws->path_info = nullptr;
    ws->query_string = nullptr;

    set.insert(*ws);
    return ws;
}

WidgetSession *
session_get_widget(Session *session, const char *id, bool create)
{
    assert(crash_in_unsafe());
    assert(session != nullptr);
    assert(id != nullptr);

    return hashmap_r_get_widget_session(session, session->widgets, id,
                                        create);
}

WidgetSession *
widget_session_get_child(WidgetSession *parent,
                         const char *id,
                         bool create)
{
    assert(crash_in_unsafe());
    assert(parent != nullptr);
    assert(parent->session != nullptr);
    assert(id != nullptr);

    return hashmap_r_get_widget_session(parent->session, parent->children,
                                        id, create);
}

static void
widget_session_free(struct dpool *pool, WidgetSession *ws)
{
    assert(crash_in_unsafe());

    d_free(pool, ws->id);

    if (ws->path_info != nullptr)
        d_free(pool, ws->path_info);

    if (ws->query_string != nullptr)
        d_free(pool, ws->query_string);

    DeleteFromPool(pool, ws);
}

static void
widget_session_clear_map(struct dpool *pool, WidgetSession::Set &set)
{
    assert(crash_in_unsafe());
    assert(pool != nullptr);

    set.clear_and_dispose([pool](WidgetSession *ws){
            widget_session_delete(pool, ws);
        });
}

void
widget_session_delete(struct dpool *pool, WidgetSession *ws)
{
    assert(crash_in_unsafe());
    assert(pool != nullptr);
    assert(ws != nullptr);

    widget_session_clear_map(pool, ws->children);

    widget_session_free(pool, ws);
}

void
session_delete_widgets(Session *session)
{
    assert(crash_in_unsafe());
    assert(session != nullptr);

    widget_session_clear_map(session->pool, session->widgets);
}
<commit_msg>session: use unchecked version of d_strdup() to copy realm name<commit_after>/*
 * Session management.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "session.hxx"
#include "cookie_jar.hxx"
#include "shm/dpool.hxx"
#include "shm/dbuffer.hxx"
#include "expiry.h"
#include "crash.hxx"
#include "expiry.h"

#include <daemon/log.h>

#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <event.h>

#define SESSION_TTL_NEW 120

inline
Session::Session(struct dpool *_pool)
    :pool(_pool),
     expires(expiry_touch(SESSION_TTL_NEW)),
     counter(1),
     is_new(true),
     cookie_sent(false), cookie_received(false),
     realm(nullptr),
     translate(nullptr),
     user(nullptr),
     user_expires(0),
     language(nullptr),
     cookies(cookie_jar_new(*_pool))
{
    lock_init(&lock);
}

inline
Session::Session(struct dpool *_pool, const Session &src)
    :pool(_pool),
     id(src.id),
     expires(src.expires),
     counter(1),
     is_new(src.is_new),
     cookie_sent(src.cookie_sent), cookie_received(src.cookie_received),
     realm(d_strdup(pool, src.realm)),
     translate(DupBuffer(pool, src.translate)),
     user(d_strdup_checked(pool, src.user)),
     user_expires(0),
     language(d_strdup_checked(pool, src.language)),
     cookies(src.cookies->Dup(*pool))
{
    lock_init(&lock);
}

inline
Session::~Session()
{
    lock_destroy(&lock);
}

Session *
session_allocate(struct dpool *pool)
{
    return NewFromPool<Session>(pool, pool);
}

void
session_destroy(Session *session)
{
    DeleteDestroyPool(*session->pool, session);
}

/**
 * Calculates the score for purging the session: higher score means
 * more likely to be purged.
 */
unsigned
session_purge_score(const Session *session)
{
    if (session->is_new)
        return 1000;

    if (!session->cookie_received)
        return 50;

    if (session->user == nullptr)
        return 20;

    return 1;
}

void
session_clear_translate(Session *session)
{
    assert(crash_in_unsafe());
    assert(session != nullptr);

    if (!session->translate.IsEmpty()) {
        d_free(session->pool, session->translate.data);
        session->translate = nullptr;
    }
}

void
session_clear_user(Session *session)
{
    assert(crash_in_unsafe());
    assert(session != nullptr);

    if (session->user != nullptr) {
        d_free(session->pool, session->user);
        session->user = nullptr;
    }
}

void
session_clear_language(Session *session)
{
    assert(crash_in_unsafe());
    assert(session != nullptr);

    if (session->language != nullptr) {
        d_free(session->pool, session->language);
        session->language = nullptr;
    }
}

bool
session_set_translate(Session *session, ConstBuffer<void> translate)
{
    assert(crash_in_unsafe());
    assert(session != nullptr);
    assert(!translate.IsNull());

    if (!session->translate.IsNull() &&
        session->translate.size == translate.size &&
        memcmp(session->translate.data, translate.data, translate.size) == 0)
        /* same value as before: no-op */
        return true;

    session_clear_translate(session);

    session->translate = DupBuffer(session->pool, translate);
    return !session->translate.IsNull();
}

bool
session_set_user(Session *session, const char *user, unsigned max_age)
{
    assert(crash_in_unsafe());
    assert(session != nullptr);
    assert(user != nullptr);

    if (session->user == nullptr || strcmp(session->user, user) != 0) {
        session_clear_user(session);

        session->user = d_strdup(session->pool, user);
        if (session->user == nullptr)
            return false;
    }

    if (max_age == (unsigned)-1)
        /* never expires */
        session->user_expires = 0;
    else if (max_age == 0)
        /* expires immediately, use only once */
        session->user_expires = 1;
    else
        session->user_expires = expiry_touch(max_age);

    return true;
}

bool
session_set_language(Session *session, const char *language)
{
    assert(crash_in_unsafe());
    assert(session != nullptr);
    assert(language != nullptr);

    if (session->language != nullptr && strcmp(session->language, language) == 0)
        /* same value as before: no-op */
        return true;

    session_clear_language(session);

    session->language = d_strdup(session->pool, language);
    return session->language != nullptr;
}

static WidgetSession::Set
widget_session_map_dup(struct dpool *pool, const WidgetSession::Set &src,
                       Session *session, WidgetSession *parent);

gcc_malloc
static WidgetSession *
widget_session_dup(struct dpool *pool, const WidgetSession *src,
                   Session *session)
{
    assert(crash_in_unsafe());
    assert(src != nullptr);
    assert(src->id != nullptr);

    auto *dest = NewFromPool<WidgetSession>(pool);
    if (dest == nullptr)
        return nullptr;

    dest->id = d_strdup(pool, src->id);
    if (dest->id == nullptr)
        return nullptr;

    dest->children = widget_session_map_dup(pool, src->children,
                                            session, dest);

    if (src->path_info != nullptr) {
        dest->path_info = d_strdup(pool, src->path_info);
        if (dest->path_info == nullptr)
            return nullptr;
    } else
        dest->path_info = nullptr;

    if (src->query_string != nullptr) {
        dest->query_string = d_strdup(pool, src->query_string);
        if (dest->query_string == nullptr)
            return nullptr;
    } else
        dest->query_string = nullptr;

    return dest;
}

static WidgetSession::Set
widget_session_map_dup(struct dpool *pool, const WidgetSession::Set &src,
                       Session *session, WidgetSession *parent)
{
    assert(crash_in_unsafe());

    WidgetSession::Set dest;

    for (const auto &src_ws : src) {
        WidgetSession *dest_ws = widget_session_dup(pool, &src_ws, session);
        if (dest_ws == nullptr)
            break;

        dest_ws->parent = parent;
        dest_ws->session = session;

        dest.insert(*dest_ws);
    }

    return std::move(dest);
}

Session *
session_dup(struct dpool *pool, const Session *src)
{
    assert(crash_in_unsafe());

    auto *dest = NewFromPool<Session>(pool, pool, *src);
    if (dest == nullptr)
        return nullptr;

    dest->widgets = widget_session_map_dup(pool, src->widgets, dest, nullptr);
    return dest;
}

WidgetSession *
widget_session_allocate(Session *session)
{
    auto *ws = NewFromPool<WidgetSession>(session->pool);
    if (ws == nullptr)
        return nullptr;

    ws->session = session;
    return ws;
}

static WidgetSession *
hashmap_r_get_widget_session(Session *session, WidgetSession::Set &set,
                             const char *id, bool create)
{
    assert(crash_in_unsafe());
    assert(session != nullptr);
    assert(lock_is_locked(&session->lock));
    assert(id != nullptr);

    auto i = set.find(id, WidgetSession::Compare());
    if (i != set.end())
        return &*i;

    if (!create)
        return nullptr;

    auto *ws = widget_session_allocate(session);
    if (ws == nullptr)
        return nullptr;

    ws->parent = nullptr;
    ws->id = d_strdup(session->pool, id);
    if (ws->id == nullptr) {
        DeleteFromPool(session->pool, ws);
        return nullptr;
    }

    ws->path_info = nullptr;
    ws->query_string = nullptr;

    set.insert(*ws);
    return ws;
}

WidgetSession *
session_get_widget(Session *session, const char *id, bool create)
{
    assert(crash_in_unsafe());
    assert(session != nullptr);
    assert(id != nullptr);

    return hashmap_r_get_widget_session(session, session->widgets, id,
                                        create);
}

WidgetSession *
widget_session_get_child(WidgetSession *parent,
                         const char *id,
                         bool create)
{
    assert(crash_in_unsafe());
    assert(parent != nullptr);
    assert(parent->session != nullptr);
    assert(id != nullptr);

    return hashmap_r_get_widget_session(parent->session, parent->children,
                                        id, create);
}

static void
widget_session_free(struct dpool *pool, WidgetSession *ws)
{
    assert(crash_in_unsafe());

    d_free(pool, ws->id);

    if (ws->path_info != nullptr)
        d_free(pool, ws->path_info);

    if (ws->query_string != nullptr)
        d_free(pool, ws->query_string);

    DeleteFromPool(pool, ws);
}

static void
widget_session_clear_map(struct dpool *pool, WidgetSession::Set &set)
{
    assert(crash_in_unsafe());
    assert(pool != nullptr);

    set.clear_and_dispose([pool](WidgetSession *ws){
            widget_session_delete(pool, ws);
        });
}

void
widget_session_delete(struct dpool *pool, WidgetSession *ws)
{
    assert(crash_in_unsafe());
    assert(pool != nullptr);
    assert(ws != nullptr);

    widget_session_clear_map(pool, ws->children);

    widget_session_free(pool, ws);
}

void
session_delete_widgets(Session *session)
{
    assert(crash_in_unsafe());
    assert(session != nullptr);

    widget_session_clear_map(session->pool, session->widgets);
}
<|endoftext|>


<commit_before>#include <faunus/species.h>
#include <faunus/inputfile.h>
#include <faunus/textio.h>
#include <faunus/physconst.h>
#include <faunus/json.h>
#include <stdlib.h>

namespace Faunus {

  AtomData::AtomData() {
    activity=0;
    charge=0;
    dp=0;
    dprot=0;
    eps=0;
    hydrophobic=0;
    mean=0;
    muscalar=0;
    mw=1.0;
    name="UNK";
    patchtype=0;
    radius=0;
    sigma=0;
    variance=0;
    len=0;
    half_len=0;
    pswitch=0;
    pdis=0;
    pangl=0;
    panglsw=0;
    //rcutwca=0;
    //rcut=0;
    //pcangl=0;
    //pcanglsw=0;
    //pcoshalfi=0;
    //psinhalfi=0;
    chiral_angle=0;
    mu.clear();
    theta.clear();
    alpha.clear();
  }

  AtomMap::AtomMap() {
    AtomData a;
    a.id=list.size();
    a.name="UNK";
    list.push_back(a);
  }

  AtomData & AtomMap::operator[] (AtomData::Tid i) { return list.at(i); }

  AtomData & AtomMap::operator[] (string s) {
    for (auto &l_i : list)
      if (s==l_i.name)
        return l_i;
    return list.at(0);
  }

  /**
   * This will look for the keyword `atomlist` in the InputMap and
   * use value as the filename.fs
   */
  bool AtomMap::includefile(InputMap &in) {
    return includefile( in.get<string>("atomlist",filename) );
  }

  bool AtomMap::includeJSON(const string& file) {
    int n=0;
    filename=file;
    std::vector<double> test1 (3,0);
    auto j=json::open(file);
    for (auto &atom : json::object("atomlist", j)) {
      n++;
      AtomData a;
      //Tensor<double> fallback;
      //fallback.clear();
      a.name = atom.first;
      a.activity = json::value<double>(atom.second, "activity", 0);
      a.alpha << json::value<std::string>(atom.second, "alpha", "");
      a.alpha *= 4*pc::pi*pc::e0*(1e-10)*pc::kT()/(pc::e*pc::e);
      a.theta << json::value<std::string>(atom.second, "theta", "");
      a.theta *= 0.20819434; // Debye Å -> e Å^2
      a.dp = json::value<double>(atom.second, "dp", 0);
      a.dprot = json::value<double>(atom.second, "dprot", 0) * pc::pi / 180.; // deg->rads
      a.eps = json::value<double>(atom.second, "eps", 0);
      a.hydrophobic = json::value<bool>(atom.second, "hydrophobic", false);
      a.mu << json::value<std::string>(atom.second, "mu", "0 0 0");
      a.muscalar = a.mu.len()*pc::D2eA();
      if (a.mu.len()>1e-6)
        a.mu = a.mu/a.mu.len();
      a.mw = json::value<double>(atom.second, "Mw", 1.);
      a.charge = json::value<double>(atom.second, "q", 0);
      a.radius = json::value<double>(atom.second, "r", 0);
      a.sigma = 2*a.radius;
      a.sigma = json::value<double>(atom.second, "sigma", a.sigma);
      a.radius = a.sigma/2;
      a.id=AtomData::Tid( list.size() );

      a.half_len = 0.5 * json::value<double>(atom.second, "len", 0);
      a.patchtype = json::value<double>(atom.second, "patchtype", 0);
      a.pswitch = json::value<double>(atom.second, "patchswitch", 0);
      a.pdis = json::value<double>(atom.second, "patchdistance", 0);
      a.pangl = json::value<double>(atom.second, "patchangle", 0)/180.0*pc::pi;
      a.panglsw = json::value<double>(atom.second, "patchangleswitch", 0)/180.0*pc::pi;
      a.chiral_angle = json::value<double>(atom.second, "patchchiralangle", 0)/180.0*pc::pi;

      // add to particle list
      bool insert=true;
      for (auto &i : list)
        if (i.name==a.name) {
          i=a; // override existing
          insert=false;
          break;
        }
      if (insert)
        list.push_back(a);
    }
    return (n>0) ? true : false;
  }

  /**
   * This will automatically detect if the file is a JSON
   * file and call includeJSON(). If not, the old restricted
   * file format is used.
   */
  bool AtomMap::includefile(string file) {
    // is it a JSON file?
    if (file.substr(file.find_last_of(".") + 1) == "json")
      return includeJSON(file);
    AtomData a;
    string t;
    filename=file;
    std::ifstream f(filename.c_str());
    cout << "Reading atom data from '" << filename << "'. ";
    if (f) {
      cout << "OK!\n";
      while (!f.eof()) {
        f >> t;
        if (t=="Atom") {
          f >> a.name >> a.charge >> a.radius >> a.eps >> a.mw >> t;
          a.sigma=2*a.radius;
          a.hydrophobic = (t=="yes") ? true : false;
          a.id=list.size();
          list.push_back(a);
        }
      }
      return true;
    }
    cout << "FAILED!\n";
    filename+=" (n/a)";
    return false;
  }

  string AtomMap::info() {
    using namespace textio;
    char w=25;
    if (filename.empty())
      filename="(undefined)";
    std::ostringstream o;
    o << header("Atomic Species")
      << pad(SUB,w,"Number of species") << list.size() << endl
      << pad(SUB,w,"Parameter file") << filename << endl
      << indent(SUB) << "Species:";
    for (size_t i=0; i<list.size(); i++) {
      if (i%10==0)
        o << endl << indent(SUBSUB);
      o << setw(SUBSUB+1) << std::left << list[i].name;
    }
    o << endl;
    return o.str();
  }

  AtomMap atom; // Instantiate global copy

}//namespace
<commit_msg>Fixed a bug for duplicate species<commit_after>#include <faunus/species.h>
#include <faunus/inputfile.h>
#include <faunus/textio.h>
#include <faunus/physconst.h>
#include <faunus/json.h>
#include <stdlib.h>

namespace Faunus {

  AtomData::AtomData() {
    activity=0;
    charge=0;
    dp=0;
    dprot=0;
    eps=0;
    hydrophobic=0;
    mean=0;
    muscalar=0;
    mw=1.0;
    name="UNK";
    patchtype=0;
    radius=0;
    sigma=0;
    variance=0;
    len=0;
    half_len=0;
    pswitch=0;
    pdis=0;
    pangl=0;
    panglsw=0;
    //rcutwca=0;
    //rcut=0;
    //pcangl=0;
    //pcanglsw=0;
    //pcoshalfi=0;
    //psinhalfi=0;
    chiral_angle=0;
    mu.clear();
    theta.clear();
    alpha.clear();
  }

  AtomMap::AtomMap() {
    AtomData a;
    a.id=list.size();
    a.name="UNK";
    list.push_back(a);
  }

  AtomData & AtomMap::operator[] (AtomData::Tid i) {
    assert(i>=0 && i<list.size() && "Particle id not found!");
    return list.at(i);
  }

  AtomData & AtomMap::operator[] (string s) {
    for (auto &l_i : list)
      if (s==l_i.name)
        return l_i;
    return list.at(0);
  }

  /**
   * This will look for the keyword `atomlist` in the InputMap and
   * use value as the filename.fs
   */
  bool AtomMap::includefile(InputMap &in) {
    return includefile( in.get<string>("atomlist",filename) );
  }

  bool AtomMap::includeJSON(const string& file) {
    int n=0;
    filename=file;
    auto j=json::open(file);
    for (auto &atom : json::object("atomlist", j)) {
      n++;
      AtomData a;
      //Tensor<double> fallback;
      //fallback.clear();
      a.name = atom.first;
      a.activity = json::value<double>(atom.second, "activity", 0);
      a.alpha << json::value<std::string>(atom.second, "alpha", "");
      a.alpha *= 4*pc::pi*pc::e0*(1e-10)*pc::kT()/(pc::e*pc::e);
      a.theta << json::value<std::string>(atom.second, "theta", "");
      a.theta *= 0.20819434; // Debye Å -> e Å^2
      a.dp = json::value<double>(atom.second, "dp", 0);
      a.dprot = json::value<double>(atom.second, "dprot", 0) * pc::pi / 180.; // deg->rads
      a.eps = json::value<double>(atom.second, "eps", 0);
      a.hydrophobic = json::value<bool>(atom.second, "hydrophobic", false);
      a.mu << json::value<std::string>(atom.second, "mu", "0 0 0");
      a.muscalar = a.mu.len()*pc::D2eA();
      if (a.mu.len()>1e-6)
        a.mu = a.mu/a.mu.len();
      a.mw = json::value<double>(atom.second, "Mw", 1.);
      a.charge = json::value<double>(atom.second, "q", 0);
      a.radius = json::value<double>(atom.second, "r", 0);
      a.sigma = 2*a.radius;
      a.sigma = json::value<double>(atom.second, "sigma", a.sigma);
      a.radius = a.sigma/2;
      a.id=AtomData::Tid( list.size() );

      a.half_len = 0.5 * json::value<double>(atom.second, "len", 0);
      a.patchtype = json::value<double>(atom.second, "patchtype", 0);
      a.pswitch = json::value<double>(atom.second, "patchswitch", 0);
      a.pdis = json::value<double>(atom.second, "patchdistance", 0);
      a.pangl = json::value<double>(atom.second, "patchangle", 0)/180.0*pc::pi;
      a.panglsw = json::value<double>(atom.second, "patchangleswitch", 0)/180.0*pc::pi;
      a.chiral_angle = json::value<double>(atom.second, "patchchiralangle", 0)/180.0*pc::pi;

      // add to particle list
      bool insert=true;
      for (auto &i : list)
        if (i.name==a.name) {
          a.id=i.id; // keep old id and
          i=a; // override existing
          insert=false;
          break;
        }
      if (insert)
        list.push_back(a);
    }
    return (n>0) ? true : false;
  }

  /**
   * This will automatically detect if the file is a JSON
   * file and call includeJSON(). If not, the old restricted
   * file format is used.
   */
  bool AtomMap::includefile(string file) {
    // is it a JSON file?
    if (file.substr(file.find_last_of(".") + 1) == "json")
      return includeJSON(file);
    AtomData a;
    string t;
    filename=file;
    std::ifstream f(filename.c_str());
    cout << "Reading atom data from '" << filename << "'. ";
    if (f) {
      cout << "OK!\n";
      while (!f.eof()) {
        f >> t;
        if (t=="Atom") {
          f >> a.name >> a.charge >> a.radius >> a.eps >> a.mw >> t;
          a.sigma=2*a.radius;
          a.hydrophobic = (t=="yes") ? true : false;
          a.id=list.size();
          list.push_back(a);
        }
      }
      return true;
    }
    cout << "FAILED!\n";
    filename+=" (n/a)";
    return false;
  }

  string AtomMap::info() {
    using namespace textio;
    char w=25;
    if (filename.empty())
      filename="(undefined)";
    std::ostringstream o;
    o << header("Atomic Species")
      << pad(SUB,w,"Number of species") << list.size() << endl
      << pad(SUB,w,"Parameter file") << filename << endl
      << indent(SUB) << "Species:";
    for (size_t i=0; i<list.size(); i++) {
      if (i%10==0)
        o << endl << indent(SUBSUB);
      o << setw(SUBSUB+1) << std::left << list[i].name;
    }
    o << endl;
    return o.str();
  }

  AtomMap atom; // Instantiate global copy

}//namespace
<|endoftext|>


<commit_before>#include "openmc/summary.h"

#include <fmt/core.h>

#include "openmc/capi.h"
#include "openmc/cell.h"
#include "openmc/file_utils.h"
#include "openmc/hdf5_interface.h"
#include "openmc/lattice.h"
#include "openmc/material.h"
#include "openmc/mgxs_interface.h"
#include "openmc/nuclide.h"
#include "openmc/output.h"
#include "openmc/surface.h"
#include "openmc/settings.h"

namespace openmc {

void write_summary()
{
  // Display output message
  write_message("Writing summary.h5 file...", 5);

  // Create a new file using default properties.
  hid_t file = file_open("summary.h5", 'w');

  write_header(file);
  write_nuclides(file);
  write_geometry(file);
  write_materials(file);

  // Terminate access to the file.
  file_close(file);
}

void write_header(hid_t file)
{
  // Write filetype and version info
  write_attribute(file, "filetype", "summary");
  write_attribute(file, "version", VERSION_SUMMARY);
  write_attribute(file, "openmc_version", VERSION);
#ifdef GIT_SHA1
  write_attribute(file, "git_sha1", GIT_SHA1);
#endif

  // Write current date and time
  write_attribute(file, "date_and_time", time_stamp());
}

void write_nuclides(hid_t file)
{
  // Build vectors of nuclide names and awrs while only sorting nuclides from
  // macroscopics
  vector<std::string> nuc_names;
  vector<std::string> macro_names;
  vector<double> awrs;

  for (int i = 0; i < data::nuclides.size(); ++i) {
    if (settings::run_CE) {
      const auto& nuc {data::nuclides[i]};
      nuc_names.push_back(nuc->name_);
      awrs.push_back(nuc->awr_);
    } else {
      const auto& nuc {data::mg.nuclides_[i]};
      if (nuc.awr != MACROSCOPIC_AWR) {
        nuc_names.push_back(nuc.name);
        awrs.push_back(nuc.awr);
      } else {
        macro_names.push_back(nuc.name);
      }
    }
  }

  hid_t nuclide_group = create_group(file, "nuclides");
  write_attribute(nuclide_group, "n_nuclides", nuc_names.size());
  hid_t macro_group = create_group(file, "macroscopics");
  write_attribute(macro_group, "n_macroscopics", macro_names.size());
  // Write nuclide names and awrs
  if (!nuc_names.empty()) {
    // Write useful data from nuclide objects
    write_dataset(nuclide_group, "names", nuc_names);
    write_dataset(nuclide_group, "awrs", awrs);
  }
  if (!macro_names.empty()) {
    // Write useful data from macroscopic objects
    write_dataset(macro_group, "names", macro_names);
  }
  close_group(nuclide_group);
  close_group(macro_group);
}

void write_geometry(hid_t file)
{
  auto geom_group = create_group(file, "geometry");

#ifdef DAGMC
  if (settings::dagmc) {
    write_attribute(geom_group, "dagmc", 1);
    close_group(geom_group);
    return;
  }
#endif

  write_attribute(geom_group, "n_cells", model::cells.size());
  write_attribute(geom_group, "n_surfaces", model::surfaces.size());
  write_attribute(geom_group, "n_universes", model::universes.size());
  write_attribute(geom_group, "n_lattices", model::lattices.size());

  auto cells_group = create_group(geom_group, "cells");
  for (const auto& c : model::cells) c->to_hdf5(cells_group);
  close_group(cells_group);

  auto surfaces_group = create_group(geom_group, "surfaces");
  for (const auto& surf : model::surfaces) surf->to_hdf5(surfaces_group);
  close_group(surfaces_group);

  auto universes_group = create_group(geom_group, "universes");
  for (const auto& u : model::universes) u->to_hdf5(universes_group);
  close_group(universes_group);

  auto lattices_group = create_group(geom_group, "lattices");
  for (const auto& lat : model::lattices) lat->to_hdf5(lattices_group);
  close_group(lattices_group);

  close_group(geom_group);
}

void write_materials(hid_t file)
{
  // write number of materials
  write_dataset(file, "n_materials", model::materials.size());

  hid_t materials_group = create_group(file, "materials");
  for (const auto& mat : model::materials) {
    mat->to_hdf5(materials_group);
  }
  close_group(materials_group);
}

//==============================================================================
// C API
//==============================================================================

extern "C" int openmc_properties_export(const char* filename)
{
  // Set a default filename if none was passed
  std::string name = filename ? filename : "properties.h5";

  // Display output message
  auto msg = fmt::format("Exporting properties to {}...", name);
  write_message(msg, 5);

  // Create a new file using default properties.
  hid_t file = file_open(name, 'w');

  // Write metadata
  write_attribute(file, "filetype", "properties");
  write_attribute(file, "version", VERSION_STATEPOINT);
  write_attribute(file, "openmc_version", VERSION);
#ifdef GIT_SHA1
  write_attribute(file, "git_sha1", GIT_SHA1);
#endif
  write_attribute(file, "date_and_time", time_stamp());
  write_attribute(file, "path", settings::path_input);

  // Write cell properties
  auto geom_group = create_group(file, "geometry");
  write_attribute(geom_group, "n_cells", model::cells.size());
  auto cells_group = create_group(geom_group, "cells");
  for (const auto& c : model::cells) {
    c->export_properties_hdf5(cells_group);
  }
  close_group(cells_group);
  close_group(geom_group);

  // Write material properties
  hid_t materials_group = create_group(file, "materials");
  write_attribute(materials_group, "n_materials", model::materials.size());
  for (const auto& mat : model::materials) {
    mat->export_properties_hdf5(materials_group);
  }
  close_group(materials_group);

  // Terminate access to the file.
  file_close(file);
  return 0;
}

extern "C" int openmc_properties_import(const char* filename)
{
  // Display output message
  auto msg = fmt::format("Importing properties from {}...", filename);
  write_message(msg, 5);

  // Create a new file using default properties.
  if (!file_exists(filename)) {
    set_errmsg(fmt::format("File '{}' does not exist.", filename));
    return OPENMC_E_INVALID_ARGUMENT;
  }
  hid_t file = file_open(filename, 'r');

  // Ensure the filetype is correct
  std::string filetype;
  read_attribute(file, "filetype", filetype);
  if (filetype != "properties") {
    set_errmsg(fmt::format("File '{}' is not a properties file.", filename));
    return OPENMC_E_INVALID_ARGUMENT;
  }

  // Make sure number of cells matches
  auto geom_group = open_group(file, "geometry");
  int32_t n;
  read_attribute(geom_group, "n_cells", n);
  if (n != openmc::model::cells.size()) {
    set_errmsg(fmt::format("Number of cells in {} doesn't match current model.", filename));
    return OPENMC_E_GEOMETRY;
  }

  // Read cell properties
  auto cells_group = open_group(geom_group, "cells");
  for (const auto& c : model::cells) {
    c->import_properties_hdf5(cells_group);
  }
  close_group(cells_group);
  close_group(geom_group);

  // Make sure number of cells matches
  auto materials_group = open_group(file, "materials");
  read_attribute(materials_group, "n_materials", n);
  if (n != openmc::model::materials.size()) {
    set_errmsg(fmt::format("Number of materials in {} doesn't match current model.", filename));
    return OPENMC_E_GEOMETRY;
  }

  // Read material properties
  for (const auto& mat : model::materials) {
    mat->import_properties_hdf5(materials_group);
  }
  close_group(materials_group);

  // Terminate access to the file.
  file_close(file);
  return 0;
}

} // namespace openmc
<commit_msg>Make sure properties.h5 gets closed properly upon error<commit_after>#include "openmc/summary.h"

#include <fmt/core.h>

#include "openmc/capi.h"
#include "openmc/cell.h"
#include "openmc/file_utils.h"
#include "openmc/hdf5_interface.h"
#include "openmc/lattice.h"
#include "openmc/material.h"
#include "openmc/mgxs_interface.h"
#include "openmc/nuclide.h"
#include "openmc/output.h"
#include "openmc/surface.h"
#include "openmc/settings.h"

namespace openmc {

void write_summary()
{
  // Display output message
  write_message("Writing summary.h5 file...", 5);

  // Create a new file using default properties.
  hid_t file = file_open("summary.h5", 'w');

  write_header(file);
  write_nuclides(file);
  write_geometry(file);
  write_materials(file);

  // Terminate access to the file.
  file_close(file);
}

void write_header(hid_t file)
{
  // Write filetype and version info
  write_attribute(file, "filetype", "summary");
  write_attribute(file, "version", VERSION_SUMMARY);
  write_attribute(file, "openmc_version", VERSION);
#ifdef GIT_SHA1
  write_attribute(file, "git_sha1", GIT_SHA1);
#endif

  // Write current date and time
  write_attribute(file, "date_and_time", time_stamp());
}

void write_nuclides(hid_t file)
{
  // Build vectors of nuclide names and awrs while only sorting nuclides from
  // macroscopics
  vector<std::string> nuc_names;
  vector<std::string> macro_names;
  vector<double> awrs;

  for (int i = 0; i < data::nuclides.size(); ++i) {
    if (settings::run_CE) {
      const auto& nuc {data::nuclides[i]};
      nuc_names.push_back(nuc->name_);
      awrs.push_back(nuc->awr_);
    } else {
      const auto& nuc {data::mg.nuclides_[i]};
      if (nuc.awr != MACROSCOPIC_AWR) {
        nuc_names.push_back(nuc.name);
        awrs.push_back(nuc.awr);
      } else {
        macro_names.push_back(nuc.name);
      }
    }
  }

  hid_t nuclide_group = create_group(file, "nuclides");
  write_attribute(nuclide_group, "n_nuclides", nuc_names.size());
  hid_t macro_group = create_group(file, "macroscopics");
  write_attribute(macro_group, "n_macroscopics", macro_names.size());
  // Write nuclide names and awrs
  if (!nuc_names.empty()) {
    // Write useful data from nuclide objects
    write_dataset(nuclide_group, "names", nuc_names);
    write_dataset(nuclide_group, "awrs", awrs);
  }
  if (!macro_names.empty()) {
    // Write useful data from macroscopic objects
    write_dataset(macro_group, "names", macro_names);
  }
  close_group(nuclide_group);
  close_group(macro_group);
}

void write_geometry(hid_t file)
{
  auto geom_group = create_group(file, "geometry");

#ifdef DAGMC
  if (settings::dagmc) {
    write_attribute(geom_group, "dagmc", 1);
    close_group(geom_group);
    return;
  }
#endif

  write_attribute(geom_group, "n_cells", model::cells.size());
  write_attribute(geom_group, "n_surfaces", model::surfaces.size());
  write_attribute(geom_group, "n_universes", model::universes.size());
  write_attribute(geom_group, "n_lattices", model::lattices.size());

  auto cells_group = create_group(geom_group, "cells");
  for (const auto& c : model::cells) c->to_hdf5(cells_group);
  close_group(cells_group);

  auto surfaces_group = create_group(geom_group, "surfaces");
  for (const auto& surf : model::surfaces) surf->to_hdf5(surfaces_group);
  close_group(surfaces_group);

  auto universes_group = create_group(geom_group, "universes");
  for (const auto& u : model::universes) u->to_hdf5(universes_group);
  close_group(universes_group);

  auto lattices_group = create_group(geom_group, "lattices");
  for (const auto& lat : model::lattices) lat->to_hdf5(lattices_group);
  close_group(lattices_group);

  close_group(geom_group);
}

void write_materials(hid_t file)
{
  // write number of materials
  write_dataset(file, "n_materials", model::materials.size());

  hid_t materials_group = create_group(file, "materials");
  for (const auto& mat : model::materials) {
    mat->to_hdf5(materials_group);
  }
  close_group(materials_group);
}

//==============================================================================
// C API
//==============================================================================

extern "C" int openmc_properties_export(const char* filename)
{
  // Set a default filename if none was passed
  std::string name = filename ? filename : "properties.h5";

  // Display output message
  auto msg = fmt::format("Exporting properties to {}...", name);
  write_message(msg, 5);

  // Create a new file using default properties.
  hid_t file = file_open(name, 'w');

  // Write metadata
  write_attribute(file, "filetype", "properties");
  write_attribute(file, "version", VERSION_STATEPOINT);
  write_attribute(file, "openmc_version", VERSION);
#ifdef GIT_SHA1
  write_attribute(file, "git_sha1", GIT_SHA1);
#endif
  write_attribute(file, "date_and_time", time_stamp());
  write_attribute(file, "path", settings::path_input);

  // Write cell properties
  auto geom_group = create_group(file, "geometry");
  write_attribute(geom_group, "n_cells", model::cells.size());
  auto cells_group = create_group(geom_group, "cells");
  for (const auto& c : model::cells) {
    c->export_properties_hdf5(cells_group);
  }
  close_group(cells_group);
  close_group(geom_group);

  // Write material properties
  hid_t materials_group = create_group(file, "materials");
  write_attribute(materials_group, "n_materials", model::materials.size());
  for (const auto& mat : model::materials) {
    mat->export_properties_hdf5(materials_group);
  }
  close_group(materials_group);

  // Terminate access to the file.
  file_close(file);
  return 0;
}

extern "C" int openmc_properties_import(const char* filename)
{
  // Display output message
  auto msg = fmt::format("Importing properties from {}...", filename);
  write_message(msg, 5);

  // Create a new file using default properties.
  if (!file_exists(filename)) {
    set_errmsg(fmt::format("File '{}' does not exist.", filename));
    return OPENMC_E_INVALID_ARGUMENT;
  }
  hid_t file = file_open(filename, 'r');

  // Ensure the filetype is correct
  std::string filetype;
  read_attribute(file, "filetype", filetype);
  if (filetype != "properties") {
    file_close(file);
    set_errmsg(fmt::format("File '{}' is not a properties file.", filename));
    return OPENMC_E_INVALID_ARGUMENT;
  }

  // Make sure number of cells matches
  auto geom_group = open_group(file, "geometry");
  int32_t n;
  read_attribute(geom_group, "n_cells", n);
  if (n != openmc::model::cells.size()) {
    close_group(geom_group);
    file_close(file);
    set_errmsg(fmt::format("Number of cells in {} doesn't match current model.", filename));
    return OPENMC_E_GEOMETRY;
  }

  // Read cell properties
  auto cells_group = open_group(geom_group, "cells");
  for (const auto& c : model::cells) {
    c->import_properties_hdf5(cells_group);
  }
  close_group(cells_group);
  close_group(geom_group);

  // Make sure number of cells matches
  auto materials_group = open_group(file, "materials");
  read_attribute(materials_group, "n_materials", n);
  if (n != openmc::model::materials.size()) {
    close_group(materials_group);
    file_close(file);
    set_errmsg(fmt::format("Number of materials in {} doesn't match current model.", filename));
    return OPENMC_E_GEOMETRY;
  }

  // Read material properties
  for (const auto& mat : model::materials) {
    mat->import_properties_hdf5(materials_group);
  }
  close_group(materials_group);

  // Terminate access to the file.
  file_close(file);
  return 0;
}

} // namespace openmc
<|endoftext|>