<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.
 */

#include "gm.h"
#if SK_SUPPORT_GPU
#include "GrFragmentProcessor.h"
#include "GrCoordTransform.h"
#include "gl/GrGLProcessor.h"
#include "gl/builders/GrGLProgramBuilder.h"
#include "Resources.h"
#include "SkShader.h"
#include "SkStream.h"
#include "SkTypeface.h"

namespace skiagm {

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

class DCShader : public SkShader {
public:
    DCShader(const SkMatrix& matrix) : fDeviceMatrix(matrix) {}

    // This is a custom shader, so we don't need to make it
    // flattenable.  Since this class is not part of the skia library,
    // it wouldn't deserialize without linking this library anyway.
    SK_DECLARE_NOT_FLATTENABLE_PROCS(DCShader)

    bool asFragmentProcessor(GrContext*, const SkPaint& paint, const SkMatrix& viewM,
                             const SkMatrix* localMatrix, GrColor* color,
                             GrFragmentProcessor** fp) const SK_OVERRIDE;
private:
    const SkMatrix fDeviceMatrix;
};

class DCFP : public GrFragmentProcessor {
public:
    DCFP(const SkMatrix& m) : fDeviceTransform(kDevice_GrCoordSet, m) {
        this->addCoordTransform(&fDeviceTransform);
        this->initClassID<DCFP>();
    }

    void getGLProcessorKey(const GrGLCaps& caps,
                            GrProcessorKeyBuilder* b) const SK_OVERRIDE {}

    GrGLFragmentProcessor* createGLInstance() const SK_OVERRIDE {
        class DCGLFP : public GrGLFragmentProcessor {
            void emitCode(GrGLFPBuilder* builder,
                            const GrFragmentProcessor& fp,
                            const char* outputColor,
                            const char* inputColor,
                            const TransformedCoordsArray& coords,
                            const TextureSamplerArray& samplers) {
                GrGLFPFragmentBuilder* fpb = builder->getFragmentShaderBuilder();
                fpb->codeAppendf("vec2 c = %s;", fpb->ensureFSCoords2D(coords, 0).c_str());
                fpb->codeAppend("vec2 r = mod(c, vec2(20.0));");
                fpb->codeAppend("vec4 color = vec4(0.5*sin(c.x / 15.0) + 0.5,"
                                                    "0.5*cos((c.x + c.y) / 15.0) + 0.5,"
                                                    "(r.x + r.y) / 20.0,"
                                                    "distance(r, vec2(15.0)) / 20.0 + 0.2);");
                fpb->codeAppendf("color.rgb *= color.a;"
                                    "%s = color * %s;",
                                    outputColor, GrGLSLExpr4(inputColor).c_str());
            }
            void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE {}
        };
        return SkNEW(DCGLFP);
    }

    const char* name() const SK_OVERRIDE { return "DCFP"; }

    void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVERRIDE {
        inout->mulByUnknownFourComponents();
    }

private:
    bool onIsEqual(const GrFragmentProcessor&) const SK_OVERRIDE { return true; }

    GrCoordTransform fDeviceTransform;
};

bool DCShader::asFragmentProcessor(GrContext*, const SkPaint& paint, const SkMatrix& viewM,
                                   const SkMatrix* localMatrix, GrColor* color,
                                   GrFragmentProcessor** fp) const {
    *fp = SkNEW_ARGS(DCFP, (fDeviceMatrix));
    *color = GrColorPackA4(paint.getAlpha());
    return true;
}

class DCShaderGM : public GM {
public:
    DCShaderGM() {
        this->setBGColor(0xFFAABBCC);
    }

    ~DCShaderGM() SK_OVERRIDE {
        for (int i = 0; i < fPrims.count(); ++i) {
            SkDELETE(fPrims[i]);
        }
    }

protected:
    uint32_t onGetFlags() const SK_OVERRIDE {
        return kGPUOnly_Flag;
    }

    SkString onShortName() SK_OVERRIDE {
        return SkString("dcshader");
    }

    SkISize onISize() SK_OVERRIDE { return SkISize::Make(1000, 900); }

    void onOnceBeforeDraw() SK_OVERRIDE {
        struct Rect : public Prim {
            SkRect draw(SkCanvas* canvas, const SkPaint& paint) SK_OVERRIDE {
                SkRect rect = SkRect::MakeXYWH(0, 0, 50, 50);
                canvas->drawRect(rect, paint);
                return rect;
            }
        };

        struct Circle : public Prim {
            SkRect draw(SkCanvas* canvas, const SkPaint& paint) SK_OVERRIDE {
                static const SkScalar radius = 25;
                canvas->drawCircle(radius, radius, radius, paint);
                return SkRect::MakeXYWH(0, 0, 2 * radius, 2 * radius);
            }
        };

        struct RRect : public Prim {
            SkRect draw(SkCanvas* canvas, const SkPaint& paint) SK_OVERRIDE {
                SkRRect rrect;
                rrect.setRectXY(SkRect::MakeXYWH(0, 0, 50, 50), 10, 10);
                canvas->drawRRect(rrect, paint);
                return rrect.getBounds();
            }
        };

        struct DRRect : public Prim {
            SkRect draw(SkCanvas* canvas, const SkPaint& paint) SK_OVERRIDE {
                SkRRect outerRRect;
                outerRRect.setRectXY(SkRect::MakeXYWH(0, 0, 50, 50), 5, 5);
                SkRRect innerRRect;
                innerRRect.setRectXY(SkRect::MakeXYWH(5, 8, 35, 30), 8, 3);
                canvas->drawDRRect(outerRRect, innerRRect, paint);
                return outerRRect.getBounds();
            }
        };
        struct Path : public Prim {
            SkRect draw(SkCanvas* canvas, const SkPaint& paint) SK_OVERRIDE {
                SkPath path;
                path.addCircle(15, 15, 10);
                path.addOval(SkRect::MakeXYWH(2, 2, 22, 37));
                path.setFillType(SkPath::kEvenOdd_FillType);
                canvas->drawPath(path, paint);
                return path.getBounds();
            }
        };

        struct Points : public Prim {
            Points(SkCanvas::PointMode mode) : fMode(mode) {}

            SkRect draw(SkCanvas* canvas, const SkPaint& paint) SK_OVERRIDE {
                SkRandom random;
                SkPoint points[500];
                SkRect bounds = SkRect::MakeWH(50, 50);
                int count = SkToInt(SK_ARRAY_COUNT(points));
                if (SkCanvas::kPoints_PointMode != fMode) {
                    count = SkTMin(count, 10);
                }
                for (int p = 0; p < count; ++p) {
                    points[p].fX = random.nextUScalar1() * bounds.width();
                    points[p].fY = random.nextUScalar1() * bounds.width();
                }
                canvas->drawPoints(fMode, count, points, paint);
                return bounds;
            }
            SkCanvas::PointMode fMode;
        };

        struct Text : public Prim {
            SkRect draw(SkCanvas* canvas, const SkPaint& origPaint) SK_OVERRIDE {
                SkPaint paint = origPaint;
                paint.setTextSize(30.f);
                this->setFont(&paint);
                const char* text = this->text();
                static const SkVector offset = SkVector::Make(10, 10);
                canvas->drawText(text, strlen(text), offset.fX, offset.fY, paint);
                SkRect bounds;
                paint.measureText(text, strlen(text), &bounds);
                bounds.offset(offset);
                return bounds;
            }

            virtual void setFont(SkPaint* paint) {
                sk_tool_utils::set_portable_typeface(paint);
            }

            virtual const char* text() const { return "Hello, Skia!"; }
        };

        struct BmpText : public Text {
           void setFont(SkPaint* paint) SK_OVERRIDE {
               if (!fTypeface) {
                    SkString filename = GetResourcePath("/Funkster.ttf");
                    SkAutoTUnref<SkFILEStream> stream(new SkFILEStream(filename.c_str()));
                    if (!stream->isValid()) {
                        SkDebugf("Could not find Funkster.ttf, please set --resourcePath "
                                 "correctly.\n");
                        return;
                    }
                    fTypeface.reset(SkTypeface::CreateFromStream(stream));
               }
               paint->setTypeface(fTypeface);
            }

            const char* text() const SK_OVERRIDE { return "Hi, Skia!"; }

            SkAutoTUnref<SkTypeface> fTypeface;
        };
        fPrims.push_back(SkNEW(Rect));
        fPrims.push_back(SkNEW(Circle));
        fPrims.push_back(SkNEW(RRect));
        fPrims.push_back(SkNEW(DRRect));
        fPrims.push_back(SkNEW(Path));
        fPrims.push_back(SkNEW(Points(SkCanvas::kPoints_PointMode)));
        fPrims.push_back(SkNEW(Points(SkCanvas::kLines_PointMode)));
        fPrims.push_back(SkNEW(Points(SkCanvas::kPolygon_PointMode)));
        fPrims.push_back(SkNEW(Text));
        fPrims.push_back(SkNEW(BmpText));
    }

    void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        SkPaint paint;
        SkTArray<SkMatrix> devMats;
        devMats.push_back().reset();
        devMats.push_back().setRotate(45, 500, 500);
        devMats.push_back().setRotate(-30, 200, 200);
        devMats.back().setPerspX(-SkScalarToPersp(SK_Scalar1 / 2000));
        devMats.back().setPerspY(SkScalarToPersp(SK_Scalar1 / 1000));

        SkTArray<SkMatrix> viewMats;
        viewMats.push_back().setScale(0.75f, 0.75f);
        viewMats.push_back().setRotate(45, 50, 50);
        viewMats.back().postScale(0.5f, 1.1f);

        canvas->translate(10, 20);
        canvas->save();
        SkScalar tx = 0, maxTy = 0;
        static const SkScalar kW = 900;

        for (int aa = 0; aa < 2; ++aa) {
            for (int i = 0; i < fPrims.count(); ++i) {
                for (int j = 0; j < devMats.count(); ++j) {
                    for (int k = 0; k < viewMats.count(); ++k) {
                        paint.setShader(SkNEW_ARGS(DCShader, (devMats[j])))->unref();
                        paint.setAntiAlias(SkToBool(aa));
                        canvas->save();
                        canvas->concat(viewMats[k]);
                        SkRect bounds = fPrims[i]->draw(canvas, paint);
                        canvas->restore();
                        viewMats[k].mapRect(&bounds);
                        // add margins
                        bounds.fRight += 20;
                        bounds.fBottom += 20;
                        canvas->translate(bounds.fRight, 0);
                        tx += bounds.fRight;
                        maxTy = SkTMax(bounds.fBottom, maxTy);
                        if (tx > kW) {
                            tx = 0;
                            canvas->restore();
                            canvas->translate(0, maxTy);
                            canvas->save();
                            maxTy = 0;
                        }
                    }
                }
            }
        }
        canvas->restore();
    }

private:
    struct Prim {
        virtual ~Prim() {}
        virtual SkRect draw(SkCanvas*, const SkPaint&) = 0;
    };

    SkTArray<Prim*> fPrims;

    typedef GM INHERITED;
};

DEF_GM( return SkNEW(DCShaderGM); )
}
#endif
<commit_msg>Make DCShader serializable.<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.
 */

#include "gm.h"
#if SK_SUPPORT_GPU
#include "GrFragmentProcessor.h"
#include "GrCoordTransform.h"
#include "gl/GrGLProcessor.h"
#include "gl/builders/GrGLProgramBuilder.h"
#include "Resources.h"
#include "SkReadBuffer.h"
#include "SkShader.h"
#include "SkStream.h"
#include "SkTypeface.h"
#include "SkWriteBuffer.h"

namespace skiagm {

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

class DCShader : public SkShader {
public:
    DCShader(const SkMatrix& matrix) : fDeviceMatrix(matrix) {}

    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(DCShader);

    void flatten(SkWriteBuffer& buf) const SK_OVERRIDE {
        buf.writeMatrix(fDeviceMatrix);
    }

    bool asFragmentProcessor(GrContext*, const SkPaint& paint, const SkMatrix& viewM,
                             const SkMatrix* localMatrix, GrColor* color,
                             GrFragmentProcessor** fp) const SK_OVERRIDE;
private:
    const SkMatrix fDeviceMatrix;
};

SkFlattenable* DCShader::CreateProc(SkReadBuffer& buf) {
    SkMatrix matrix;
    buf.readMatrix(&matrix);
    return SkNEW_ARGS(DCShader, (matrix));
}

class DCFP : public GrFragmentProcessor {
public:
    DCFP(const SkMatrix& m) : fDeviceTransform(kDevice_GrCoordSet, m) {
        this->addCoordTransform(&fDeviceTransform);
        this->initClassID<DCFP>();
    }

    void getGLProcessorKey(const GrGLCaps& caps,
                            GrProcessorKeyBuilder* b) const SK_OVERRIDE {}

    GrGLFragmentProcessor* createGLInstance() const SK_OVERRIDE {
        class DCGLFP : public GrGLFragmentProcessor {
            void emitCode(GrGLFPBuilder* builder,
                            const GrFragmentProcessor& fp,
                            const char* outputColor,
                            const char* inputColor,
                            const TransformedCoordsArray& coords,
                            const TextureSamplerArray& samplers) {
                GrGLFPFragmentBuilder* fpb = builder->getFragmentShaderBuilder();
                fpb->codeAppendf("vec2 c = %s;", fpb->ensureFSCoords2D(coords, 0).c_str());
                fpb->codeAppend("vec2 r = mod(c, vec2(20.0));");
                fpb->codeAppend("vec4 color = vec4(0.5*sin(c.x / 15.0) + 0.5,"
                                                    "0.5*cos((c.x + c.y) / 15.0) + 0.5,"
                                                    "(r.x + r.y) / 20.0,"
                                                    "distance(r, vec2(15.0)) / 20.0 + 0.2);");
                fpb->codeAppendf("color.rgb *= color.a;"
                                    "%s = color * %s;",
                                    outputColor, GrGLSLExpr4(inputColor).c_str());
            }
            void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE {}
        };
        return SkNEW(DCGLFP);
    }

    const char* name() const SK_OVERRIDE { return "DCFP"; }

    void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVERRIDE {
        inout->mulByUnknownFourComponents();
    }

private:
    bool onIsEqual(const GrFragmentProcessor&) const SK_OVERRIDE { return true; }

    GrCoordTransform fDeviceTransform;
};

bool DCShader::asFragmentProcessor(GrContext*, const SkPaint& paint, const SkMatrix& viewM,
                                   const SkMatrix* localMatrix, GrColor* color,
                                   GrFragmentProcessor** fp) const {
    *fp = SkNEW_ARGS(DCFP, (fDeviceMatrix));
    *color = GrColorPackA4(paint.getAlpha());
    return true;
}

class DCShaderGM : public GM {
public:
    DCShaderGM() {
        this->setBGColor(0xFFAABBCC);
    }

    ~DCShaderGM() SK_OVERRIDE {
        for (int i = 0; i < fPrims.count(); ++i) {
            SkDELETE(fPrims[i]);
        }
    }

protected:
    uint32_t onGetFlags() const SK_OVERRIDE {
        return kGPUOnly_Flag;
    }

    SkString onShortName() SK_OVERRIDE {
        return SkString("dcshader");
    }

    SkISize onISize() SK_OVERRIDE { return SkISize::Make(1000, 900); }

    void onOnceBeforeDraw() SK_OVERRIDE {
        struct Rect : public Prim {
            SkRect draw(SkCanvas* canvas, const SkPaint& paint) SK_OVERRIDE {
                SkRect rect = SkRect::MakeXYWH(0, 0, 50, 50);
                canvas->drawRect(rect, paint);
                return rect;
            }
        };

        struct Circle : public Prim {
            SkRect draw(SkCanvas* canvas, const SkPaint& paint) SK_OVERRIDE {
                static const SkScalar radius = 25;
                canvas->drawCircle(radius, radius, radius, paint);
                return SkRect::MakeXYWH(0, 0, 2 * radius, 2 * radius);
            }
        };

        struct RRect : public Prim {
            SkRect draw(SkCanvas* canvas, const SkPaint& paint) SK_OVERRIDE {
                SkRRect rrect;
                rrect.setRectXY(SkRect::MakeXYWH(0, 0, 50, 50), 10, 10);
                canvas->drawRRect(rrect, paint);
                return rrect.getBounds();
            }
        };

        struct DRRect : public Prim {
            SkRect draw(SkCanvas* canvas, const SkPaint& paint) SK_OVERRIDE {
                SkRRect outerRRect;
                outerRRect.setRectXY(SkRect::MakeXYWH(0, 0, 50, 50), 5, 5);
                SkRRect innerRRect;
                innerRRect.setRectXY(SkRect::MakeXYWH(5, 8, 35, 30), 8, 3);
                canvas->drawDRRect(outerRRect, innerRRect, paint);
                return outerRRect.getBounds();
            }
        };
        struct Path : public Prim {
            SkRect draw(SkCanvas* canvas, const SkPaint& paint) SK_OVERRIDE {
                SkPath path;
                path.addCircle(15, 15, 10);
                path.addOval(SkRect::MakeXYWH(2, 2, 22, 37));
                path.setFillType(SkPath::kEvenOdd_FillType);
                canvas->drawPath(path, paint);
                return path.getBounds();
            }
        };

        struct Points : public Prim {
            Points(SkCanvas::PointMode mode) : fMode(mode) {}

            SkRect draw(SkCanvas* canvas, const SkPaint& paint) SK_OVERRIDE {
                SkRandom random;
                SkPoint points[500];
                SkRect bounds = SkRect::MakeWH(50, 50);
                int count = SkToInt(SK_ARRAY_COUNT(points));
                if (SkCanvas::kPoints_PointMode != fMode) {
                    count = SkTMin(count, 10);
                }
                for (int p = 0; p < count; ++p) {
                    points[p].fX = random.nextUScalar1() * bounds.width();
                    points[p].fY = random.nextUScalar1() * bounds.width();
                }
                canvas->drawPoints(fMode, count, points, paint);
                return bounds;
            }
            SkCanvas::PointMode fMode;
        };

        struct Text : public Prim {
            SkRect draw(SkCanvas* canvas, const SkPaint& origPaint) SK_OVERRIDE {
                SkPaint paint = origPaint;
                paint.setTextSize(30.f);
                this->setFont(&paint);
                const char* text = this->text();
                static const SkVector offset = SkVector::Make(10, 10);
                canvas->drawText(text, strlen(text), offset.fX, offset.fY, paint);
                SkRect bounds;
                paint.measureText(text, strlen(text), &bounds);
                bounds.offset(offset);
                return bounds;
            }

            virtual void setFont(SkPaint* paint) {
                sk_tool_utils::set_portable_typeface(paint);
            }

            virtual const char* text() const { return "Hello, Skia!"; }
        };

        struct BmpText : public Text {
           void setFont(SkPaint* paint) SK_OVERRIDE {
               if (!fTypeface) {
                    SkString filename = GetResourcePath("/Funkster.ttf");
                    SkAutoTUnref<SkFILEStream> stream(new SkFILEStream(filename.c_str()));
                    if (!stream->isValid()) {
                        SkDebugf("Could not find Funkster.ttf, please set --resourcePath "
                                 "correctly.\n");
                        return;
                    }
                    fTypeface.reset(SkTypeface::CreateFromStream(stream));
               }
               paint->setTypeface(fTypeface);
            }

            const char* text() const SK_OVERRIDE { return "Hi, Skia!"; }

            SkAutoTUnref<SkTypeface> fTypeface;
        };
        fPrims.push_back(SkNEW(Rect));
        fPrims.push_back(SkNEW(Circle));
        fPrims.push_back(SkNEW(RRect));
        fPrims.push_back(SkNEW(DRRect));
        fPrims.push_back(SkNEW(Path));
        fPrims.push_back(SkNEW(Points(SkCanvas::kPoints_PointMode)));
        fPrims.push_back(SkNEW(Points(SkCanvas::kLines_PointMode)));
        fPrims.push_back(SkNEW(Points(SkCanvas::kPolygon_PointMode)));
        fPrims.push_back(SkNEW(Text));
        fPrims.push_back(SkNEW(BmpText));
    }

    void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        SkPaint paint;
        SkTArray<SkMatrix> devMats;
        devMats.push_back().reset();
        devMats.push_back().setRotate(45, 500, 500);
        devMats.push_back().setRotate(-30, 200, 200);
        devMats.back().setPerspX(-SkScalarToPersp(SK_Scalar1 / 2000));
        devMats.back().setPerspY(SkScalarToPersp(SK_Scalar1 / 1000));

        SkTArray<SkMatrix> viewMats;
        viewMats.push_back().setScale(0.75f, 0.75f);
        viewMats.push_back().setRotate(45, 50, 50);
        viewMats.back().postScale(0.5f, 1.1f);

        canvas->translate(10, 20);
        canvas->save();
        SkScalar tx = 0, maxTy = 0;
        static const SkScalar kW = 900;

        for (int aa = 0; aa < 2; ++aa) {
            for (int i = 0; i < fPrims.count(); ++i) {
                for (int j = 0; j < devMats.count(); ++j) {
                    for (int k = 0; k < viewMats.count(); ++k) {
                        paint.setShader(SkNEW_ARGS(DCShader, (devMats[j])))->unref();
                        paint.setAntiAlias(SkToBool(aa));
                        canvas->save();
                        canvas->concat(viewMats[k]);
                        SkRect bounds = fPrims[i]->draw(canvas, paint);
                        canvas->restore();
                        viewMats[k].mapRect(&bounds);
                        // add margins
                        bounds.fRight += 20;
                        bounds.fBottom += 20;
                        canvas->translate(bounds.fRight, 0);
                        tx += bounds.fRight;
                        maxTy = SkTMax(bounds.fBottom, maxTy);
                        if (tx > kW) {
                            tx = 0;
                            canvas->restore();
                            canvas->translate(0, maxTy);
                            canvas->save();
                            maxTy = 0;
                        }
                    }
                }
            }
        }
        canvas->restore();
    }

private:
    struct Prim {
        virtual ~Prim() {}
        virtual SkRect draw(SkCanvas*, const SkPaint&) = 0;
    };

    SkTArray<Prim*> fPrims;

    typedef GM INHERITED;
};

DEF_GM( return SkNEW(DCShaderGM); )
}
#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: hatchwindowfactory.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: kz $ $Date: 2004-10-04 19:46:51 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _XHATCHWINDOWFACTORY_HXX_
#define _XHATCHWINDOWFACTORY_HXX_

#ifndef _COM_SUN_STAR_EMBED_XHATCHWINDOWFACTORY_HPP_
#include <com/sun/star/embed/XHatchWindowFactory.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE5_HXX_
#include <cppuhelper/implbase2.hxx>
#endif

class OHatchWindowFactory : public ::cppu::WeakImplHelper2<
                                                ::com::sun::star::embed::XHatchWindowFactory,
                                                ::com::sun::star::lang::XServiceInfo >
{
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xFactory;

public:
    OHatchWindowFactory(
        const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory )
    : m_xFactory( xFactory )
    {
        OSL_ENSURE( xFactory.is(), "No service manager is provided!\n" );
    }

    static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL impl_staticGetSupportedServiceNames();

    static ::rtl::OUString SAL_CALL impl_staticGetImplementationName();

    static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
        impl_staticCreateSelfInstance(
            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager );

    // XHatchWindowFactory
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::embed::XHatchWindow > SAL_CALL createHatchWindowInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer >& xParent, const ::com::sun::star::awt::Rectangle& aBounds, const ::com::sun::star::awt::Size& aSize ) throw (::com::sun::star::uno::RuntimeException);

    // XServiceInfo
    virtual ::rtl::OUString SAL_CALL getImplementationName() throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw (::com::sun::star::uno::RuntimeException);

};

#endif

<commit_msg>INTEGRATION: CWS ooo19126 (1.2.380); FILE MERGED 2005/09/05 14:53:16 rt 1.2.380.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: hatchwindowfactory.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 15:54:23 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _XHATCHWINDOWFACTORY_HXX_
#define _XHATCHWINDOWFACTORY_HXX_

#ifndef _COM_SUN_STAR_EMBED_XHATCHWINDOWFACTORY_HPP_
#include <com/sun/star/embed/XHatchWindowFactory.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE5_HXX_
#include <cppuhelper/implbase2.hxx>
#endif

class OHatchWindowFactory : public ::cppu::WeakImplHelper2<
                                                ::com::sun::star::embed::XHatchWindowFactory,
                                                ::com::sun::star::lang::XServiceInfo >
{
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xFactory;

public:
    OHatchWindowFactory(
        const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory )
    : m_xFactory( xFactory )
    {
        OSL_ENSURE( xFactory.is(), "No service manager is provided!\n" );
    }

    static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL impl_staticGetSupportedServiceNames();

    static ::rtl::OUString SAL_CALL impl_staticGetImplementationName();

    static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
        impl_staticCreateSelfInstance(
            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager );

    // XHatchWindowFactory
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::embed::XHatchWindow > SAL_CALL createHatchWindowInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer >& xParent, const ::com::sun::star::awt::Rectangle& aBounds, const ::com::sun::star::awt::Size& aSize ) throw (::com::sun::star::uno::RuntimeException);

    // XServiceInfo
    virtual ::rtl::OUString SAL_CALL getImplementationName() throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw (::com::sun::star::uno::RuntimeException);

};

#endif

<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
const ll M = 1000000007;

typedef tuple<ll, int, int> key; // bit, backback, back

vector<ll> connected[60][60];

map<key, ll> dp;

int N;
vector<int> V[60];

void make_connected(int x, int y) {
  bool visited[60];
  fill(visited, visited+60, false);
  visited[x] = true;
  visited[y] = true;
  for (auto i = 0; i < N; ++i) {
    if (visited[i]) continue;
    ll ans = 0;
    stack<int> S;
    S.push(i);
    while (!S.empty()) {
      int now = S.top();
      S.pop();
      if (!visited[now]) {
        visited[now] = true;
        ans += 1ll << now;
        for (auto e : V[now]) {
          if (!visited[e]) {
            S.push(e);
          }
        }
      }
    }
    connected[x][y].push_back(ans);
  }
  connected[y][x] = connected[x][y];
}

inline bool all_or_nothing(const ll& bit, const ll& con) {
  if ((bit & con) == con) return true;
  // ll hanten = ((1ll << 55) - 1) ^ bit;
  return (((((1ll << 55) - 1) ^ bit) & con) == con);
}

inline bool valid(key k) {
  const ll& bit = get<0>(k);
  const int& a = get<1>(k);
  const int& b = get<2>(k);
  for (auto& x : connected[a][b]) {
    if (!(all_or_nothing(bit, x))) return false;
  }
  return true;
}

inline int cnt_one(ll bit) {
  int cnt = 0;
  while (bit > 0) {
    if ((bit & 1ll) == 1) ++cnt;
    bit = (bit >> 1);
  }
  return cnt;
}

ll value(key k) {
  ll bit = get<0>(k);
  int c = cnt_one(bit);
  // if (c == 1) return 1;
  if (!valid(k)) return 0;
  if (c == 2) return 1;
  auto it = dp.find(k);
  if (it != dp.end()) return (*it).second;
  ll ans = 0;
  const int& a = get<1>(k);
  const int& b = get<2>(k);
  bit -= (1ll << b);
  for (auto i = 0; i < N; ++i) {
    if (i == a) continue;
    if ((bit & (1ll << i)) == 0) continue;
    ans += value(key(bit, i, a));
    ans %= M;
  }
  dp[k] = ans;
  return ans;
}

int main () {
  cin >> N;
  for (auto i = 0; i < N-1; ++i) {
    int a, b;
    cin >> a >> b;
    --a;
    --b;
  }
  if (N == 1) {
    cout << 1 << endl;
    return 0;
  } else if (N == 2) {
    cout << 2 << endl;
    return 0;
  }
  for (auto i = 0; i < N; ++i) {
    if (V[i].size() > 4) {
      cout << 0 << endl;
      return 0;
    }
  }
  for (auto i = 0; i < N; ++i) {
    for (auto j = i+1; j < N; ++j) {
      make_connected(i, j);
    }
  }
  ll ans = 0;
  for (auto i = 0; i < N; ++i) {
    for (auto j = 0; j < N; ++j) {
      if (i == j) continue;
      cerr << "i = " << i << ", j = " << j << ", val = "
           << value(key(((1ll << N) - 1), i, j)) << endl;
      ans += value(key(((1ll << N) - 1), i, j));
      ans %= M;
    }
  }
  cout << ans << endl;
}
<commit_msg>tried D.cpp to 'D'<commit_after>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
const ll M = 1000000007;

typedef tuple<ll, int, int> key; // bit, backback, back

vector<ll> connected[60][60];

map<key, ll> dp;

int N;
vector<int> V[60];

void make_connected(int x, int y) {
  bool visited[60];
  fill(visited, visited+60, false);
  visited[x] = true;
  visited[y] = true;
  for (auto i = 0; i < N; ++i) {
    if (visited[i]) continue;
    ll ans = 0;
    stack<int> S;
    S.push(i);
    while (!S.empty()) {
      int now = S.top();
      S.pop();
      if (!visited[now]) {
        visited[now] = true;
        ans += 1ll << now;
        for (auto e : V[now]) {
          if (!visited[e]) {
            S.push(e);
          }
        }
      }
    }
    connected[x][y].push_back(ans);
  }
  connected[y][x] = connected[x][y];
}

inline bool all_or_nothing(const ll& bit, const ll& con) {
  ll hanten = ((1ll << N) - 1) ^ bit;
  cerr << "bit = " << bit << ", con = " << con
       << ", hanten = " << hanten << endl;
  if ((bit & con) == con) {
    return true;
  }
  return (((((1ll << N) - 1) ^ bit) & con) == con);
}

inline bool valid(key k) {
  const ll& bit = get<0>(k);
  const int& a = get<1>(k);
  const int& b = get<2>(k);
  for (auto& x : connected[a][b]) {
    if (!(all_or_nothing(bit, x))) return false;
  }
  return true;
}

inline int cnt_one(ll bit) {
  int cnt = 0;
  while (bit > 0) {
    if ((bit & 1ll) == 1) ++cnt;
    bit = (bit >> 1);
  }
  return cnt;
}

ll value(key k) {
  ll bit = get<0>(k);
  int c = cnt_one(bit);
  // if (c == 1) return 1;
  if (!valid(k)) return 0;
  if (c == 2) return 1;
  auto it = dp.find(k);
  if (it != dp.end()) return (*it).second;
  ll ans = 0;
  const int& a = get<1>(k);
  const int& b = get<2>(k);
  bit -= (1ll << b);
  for (auto i = 0; i < N; ++i) {
    if (i == a) continue;
    if ((bit & (1ll << i)) == 0) continue;
    ans += value(key(bit, i, a));
    ans %= M;
  }
  dp[k] = ans;
  return ans;
}

int main () {
  cin >> N;
  for (auto i = 0; i < N-1; ++i) {
    int a, b;
    cin >> a >> b;
    --a;
    --b;
  }
  if (N == 1) {
    cout << 1 << endl;
    return 0;
  } else if (N == 2) {
    cout << 2 << endl;
    return 0;
  }
  for (auto i = 0; i < N; ++i) {
    if (V[i].size() > 4) {
      cout << 0 << endl;
      return 0;
    }
  }
  for (auto i = 0; i < N; ++i) {
    for (auto j = i+1; j < N; ++j) {
      make_connected(i, j);
    }
  }
  ll ans = 0;
  for (auto i = 0; i < N; ++i) {
    for (auto j = 0; j < N; ++j) {
      if (i == j) continue;
      cerr << "i = " << i << ", j = " << j << ", val = "
           << value(key(((1ll << N) - 1), i, j)) << endl;
      ans += value(key(((1ll << N) - 1), i, j));
      ans %= M;
    }
  }
  cout << ans << endl;
}
<|endoftext|>


<commit_before>// Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/

#include "Spc_Emu.h"

#include "blargg_endian.h"
#include <stdlib.h>
#include <string.h>

/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */

#include "blargg_source.h"

// TODO: support Spc_Filter's bass

Spc_Emu::Spc_Emu()
{
	set_type( gme_spc_type );

	static const char* const names [Snes_Spc::voice_count] = {
		"DSP 1", "DSP 2", "DSP 3", "DSP 4", "DSP 5", "DSP 6", "DSP 7", "DSP 8"
	};
	set_voice_names( names );

	set_gain( 1.4 );
}

Spc_Emu::~Spc_Emu() { }

// Track info

long const trailer_offset = 0x10200;

byte const* Spc_Emu::trailer() const { return &file_data [min( file_size, trailer_offset )]; }

long Spc_Emu::trailer_size() const { return max( 0L, file_size - trailer_offset ); }

static void get_spc_xid6( byte const* begin, long size, track_info_t* out )
{
	// header
	byte const* end = begin + size;
	if ( size < 8 || memcmp( begin, "xid6", 4 ) )
	{
		check( false );
		return;
	}
	long info_size = get_le32( begin + 4 );
	byte const* in = begin + 8;
	if ( end - in > info_size )
	{
		debug_printf( "Extra data after SPC xid6 info\n" );
		end = in + info_size;
	}

	int year = 0;
	char copyright [256 + 5];
	int copyright_len = 0;
	int const year_len = 5;

	while ( end - in >= 4 )
	{
		// header
		int id   = in [0];
		int data = in [3] * 0x100 + in [2];
		int type = in [1];
		int len  = type ? data : 0;
		in += 4;
		if ( len > end - in )
		{
			check( false );
			break; // block goes past end of data
		}

		// handle specific block types
		char* field = 0;
		switch ( id )
		{
			case 0x01: field = out->song;    break;
			case 0x02: field = out->game;    break;
			case 0x03: field = out->author;  break;
			case 0x04: field = out->dumper;  break;
			case 0x07: field = out->comment; break;
			case 0x14: year = data;          break;

			//case 0x30: // intro length
			// Many SPCs have intro length set wrong for looped tracks, making it useless
			/*
			case 0x30:
				check( len == 4 );
				if ( len >= 4 )
				{
					out->intro_length = get_le32( in ) / 64;
					if ( out->length > 0 )
					{
						long loop = out->length - out->intro_length;
						if ( loop >= 2000 )
							out->loop_length = loop;
					}
				}
				break;
			*/

			case 0x13:
				copyright_len = min( len, (int) sizeof copyright - year_len );
				memcpy( &copyright [year_len], in, copyright_len );
				break;

			default:
				if ( id < 0x01 || (id > 0x07 && id < 0x10) ||
						(id > 0x14 && id < 0x30) || id > 0x36 )
					debug_printf( "Unknown SPC xid6 block: %X\n", (int) id );
				break;
		}
		if ( field )
		{
			check( type == 1 );
			Gme_File::copy_field_( field, (char const*) in, len );
		}

		// skip to next block
		in += len;

		// blocks are supposed to be 4-byte aligned with zero-padding...
		byte const* unaligned = in;
		while ( (in - begin) & 3 && in < end )
		{
			if ( *in++ != 0 )
			{
				// ...but some files have no padding
				in = unaligned;
				debug_printf( "SPC info tag wasn't properly padded to align\n" );
				break;
			}
		}
	}

	char* p = &copyright [year_len];
	if ( year )
	{
		*--p = ' ';
		for ( int n = 4; n--; )
		{
			*--p = char (year % 10 + '0');
			year /= 10;
		}
		copyright_len += year_len;
	}
	if ( copyright_len )
		Gme_File::copy_field_( out->copyright, p, copyright_len );

	check( in == end );
}

static void get_spc_info( Spc_Emu::header_t const& h, byte const* xid6, long xid6_size,
		track_info_t* out )
{
	// decode length (can be in text or binary format, sometimes ambiguous ugh)
	long len_secs = 0;
	for ( int i = 0; i < 3; i++ )
	{
		unsigned n = h.len_secs [i] - '0';
		if ( n > 9 )
		{
			// ignore single-digit text lengths
			// (except if author field is present and begins at offset 1, ugh)
			if ( i == 1 && (h.author [0] || !h.author [1]) )
				len_secs = 0;
			break;
		}
		len_secs *= 10;
		len_secs += n;
	}
	if ( !len_secs || len_secs > 0x1FFF )
		len_secs = get_le16( h.len_secs );
	if ( len_secs < 0x1FFF )
		out->length = len_secs * 1000;

	int offset = (h.author [0] < ' ' || unsigned (h.author [0] - '0') <= 9);
	Gme_File::copy_field_( out->author, &h.author [offset], sizeof h.author - offset );

	GME_COPY_FIELD( h, out, song );
	GME_COPY_FIELD( h, out, game );
	GME_COPY_FIELD( h, out, dumper );
	GME_COPY_FIELD( h, out, comment );

	if ( xid6_size )
		get_spc_xid6( xid6, xid6_size, out );
}

blargg_err_t Spc_Emu::track_info_( track_info_t* out, int ) const
{
	get_spc_info( header(), trailer(), trailer_size(), out );
	return 0;
}

static blargg_err_t check_spc_header( void const* header )
{
	if ( memcmp( header, "SNES-SPC700 Sound File Data", 27 ) )
		return gme_wrong_file_type;
	return 0;
}

struct Spc_File : Gme_Info_
{
	Spc_Emu::header_t header;
	blargg_vector<byte> xid6;

	Spc_File() { set_type( gme_spc_type ); }

	blargg_err_t load_( Data_Reader& in )
	{
		long file_size = in.remain();
		if ( file_size < Snes_Spc::spc_min_file_size )
			return gme_wrong_file_type;
		RETURN_ERR( in.read( &header, Spc_Emu::header_size ) );
		RETURN_ERR( check_spc_header( header.tag ) );
		long const xid6_offset = 0x10200;
		long xid6_size = file_size - xid6_offset;
		if ( xid6_size > 0 )
		{
			RETURN_ERR( xid6.resize( xid6_size ) );
			RETURN_ERR( in.skip( xid6_offset - Spc_Emu::header_size ) );
			RETURN_ERR( in.read( xid6.begin(), xid6.size() ) );
		}
		return 0;
	}

	blargg_err_t track_info_( track_info_t* out, int ) const
	{
		get_spc_info( header, xid6.begin(), xid6.size(), out );
		return 0;
	}
};

static Music_Emu* new_spc_emu () { return BLARGG_NEW Spc_Emu ; }
static Music_Emu* new_spc_file() { return BLARGG_NEW Spc_File; }

static gme_type_t_ const gme_spc_type_ = { "Super Nintendo", 1, &new_spc_emu, &new_spc_file, "SPC", 0 };
BLARGG_EXPORT extern gme_type_t const gme_spc_type = &gme_spc_type_;

// Setup

blargg_err_t Spc_Emu::set_sample_rate_( long sample_rate )
{
	RETURN_ERR( apu.init() );
	enable_accuracy( false );
	if ( sample_rate != native_sample_rate )
	{
		RETURN_ERR( resampler.buffer_size( native_sample_rate / 20 * 2 ) );
		resampler.time_ratio( (double) native_sample_rate / sample_rate, 0.9965 );
	}
	return 0;
}

void Spc_Emu::enable_accuracy_( bool b )
{
	Music_Emu::enable_accuracy_( b );
	filter.enable( b );
}

void Spc_Emu::mute_voices_( int m )
{
	Music_Emu::mute_voices_( m );
	apu.mute_voices( m );
}

blargg_err_t Spc_Emu::load_mem_( byte const* in, long size )
{
	assert( offsetof (header_t,unused2 [46]) == header_size );
	file_data = in;
	file_size = size;
	set_voice_count( Snes_Spc::voice_count );
	if ( size < Snes_Spc::spc_min_file_size )
		return gme_wrong_file_type;
	return check_spc_header( in );
}

// Emulation

void Spc_Emu::set_tempo_( double t )
{
	apu.set_tempo( (int) (t * apu.tempo_unit) );
}

blargg_err_t Spc_Emu::start_track_( int track )
{
	RETURN_ERR( Music_Emu::start_track_( track ) );
	resampler.clear();
	filter.clear();
	RETURN_ERR( apu.load_spc( file_data, file_size ) );
	filter.set_gain( (int) (gain() * SPC_Filter::gain_unit) );
	apu.clear_echo();
	return 0;
}

blargg_err_t Spc_Emu::play_and_filter( long count, sample_t out [] )
{
	RETURN_ERR( apu.play( count, out ) );
	filter.run( out, count );
	return 0;
}

blargg_err_t Spc_Emu::skip_( long count )
{
	if ( sample_rate() != native_sample_rate )
	{
		count = long (count * resampler.ratio()) & ~1;
		count -= resampler.skip_input( count );
	}

	// TODO: shouldn't skip be adjusted for the 64 samples read afterwards?

	if ( count > 0 )
	{
		RETURN_ERR( apu.skip( count ) );
		filter.clear();
	}

	// eliminate pop due to resampler
	const int resampler_latency = 64;
	sample_t buf [resampler_latency];
	return play_( resampler_latency, buf );
}

blargg_err_t Spc_Emu::play_( long count, sample_t* out )
{
	if ( sample_rate() == native_sample_rate )
		return play_and_filter( count, out );

	long remain = count;
	while ( remain > 0 )
	{
		remain -= resampler.read( &out [count - remain], remain );
		if ( remain > 0 )
		{
			long n = resampler.max_write();
			RETURN_ERR( play_and_filter( n, resampler.buffer() ) );
			resampler.write( n );
		}
	}
	check( remain == 0 );
	return 0;
}
<commit_msg>spc: Set a playback length by default if set in header.<commit_after>// Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/

#include "Spc_Emu.h"

#include "blargg_endian.h"
#include <stdlib.h>
#include <string.h>

/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */

#include "blargg_source.h"

// TODO: support Spc_Filter's bass

Spc_Emu::Spc_Emu()
{
	set_type( gme_spc_type );

	static const char* const names [Snes_Spc::voice_count] = {
		"DSP 1", "DSP 2", "DSP 3", "DSP 4", "DSP 5", "DSP 6", "DSP 7", "DSP 8"
	};
	set_voice_names( names );

	set_gain( 1.4 );
}

Spc_Emu::~Spc_Emu() { }

// Track info

long const trailer_offset = 0x10200;

byte const* Spc_Emu::trailer() const { return &file_data [min( file_size, trailer_offset )]; }

long Spc_Emu::trailer_size() const { return max( 0L, file_size - trailer_offset ); }

static void get_spc_xid6( byte const* begin, long size, track_info_t* out )
{
	// header
	byte const* end = begin + size;
	if ( size < 8 || memcmp( begin, "xid6", 4 ) )
	{
		check( false );
		return;
	}
	long info_size = get_le32( begin + 4 );
	byte const* in = begin + 8;
	if ( end - in > info_size )
	{
		debug_printf( "Extra data after SPC xid6 info\n" );
		end = in + info_size;
	}

	int year = 0;
	char copyright [256 + 5];
	int copyright_len = 0;
	int const year_len = 5;

	while ( end - in >= 4 )
	{
		// header
		int id   = in [0];
		int data = in [3] * 0x100 + in [2];
		int type = in [1];
		int len  = type ? data : 0;
		in += 4;
		if ( len > end - in )
		{
			check( false );
			break; // block goes past end of data
		}

		// handle specific block types
		char* field = 0;
		switch ( id )
		{
			case 0x01: field = out->song;    break;
			case 0x02: field = out->game;    break;
			case 0x03: field = out->author;  break;
			case 0x04: field = out->dumper;  break;
			case 0x07: field = out->comment; break;
			case 0x14: year = data;          break;

			//case 0x30: // intro length
			// Many SPCs have intro length set wrong for looped tracks, making it useless
			/*
			case 0x30:
				check( len == 4 );
				if ( len >= 4 )
				{
					out->intro_length = get_le32( in ) / 64;
					if ( out->length > 0 )
					{
						long loop = out->length - out->intro_length;
						if ( loop >= 2000 )
							out->loop_length = loop;
					}
				}
				break;
			*/

			case 0x13:
				copyright_len = min( len, (int) sizeof copyright - year_len );
				memcpy( &copyright [year_len], in, copyright_len );
				break;

			default:
				if ( id < 0x01 || (id > 0x07 && id < 0x10) ||
						(id > 0x14 && id < 0x30) || id > 0x36 )
					debug_printf( "Unknown SPC xid6 block: %X\n", (int) id );
				break;
		}
		if ( field )
		{
			check( type == 1 );
			Gme_File::copy_field_( field, (char const*) in, len );
		}

		// skip to next block
		in += len;

		// blocks are supposed to be 4-byte aligned with zero-padding...
		byte const* unaligned = in;
		while ( (in - begin) & 3 && in < end )
		{
			if ( *in++ != 0 )
			{
				// ...but some files have no padding
				in = unaligned;
				debug_printf( "SPC info tag wasn't properly padded to align\n" );
				break;
			}
		}
	}

	char* p = &copyright [year_len];
	if ( year )
	{
		*--p = ' ';
		for ( int n = 4; n--; )
		{
			*--p = char (year % 10 + '0');
			year /= 10;
		}
		copyright_len += year_len;
	}
	if ( copyright_len )
		Gme_File::copy_field_( out->copyright, p, copyright_len );

	check( in == end );
}

static void get_spc_info( Spc_Emu::header_t const& h, byte const* xid6, long xid6_size,
		track_info_t* out )
{
	// decode length (can be in text or binary format, sometimes ambiguous ugh)
	long len_secs = 0;
	for ( int i = 0; i < 3; i++ )
	{
		unsigned n = h.len_secs [i] - '0';
		if ( n > 9 )
		{
			// ignore single-digit text lengths
			// (except if author field is present and begins at offset 1, ugh)
			if ( i == 1 && (h.author [0] || !h.author [1]) )
				len_secs = 0;
			break;
		}
		len_secs *= 10;
		len_secs += n;
	}
	if ( !len_secs || len_secs > 0x1FFF )
		len_secs = get_le16( h.len_secs );
	if ( len_secs < 0x1FFF )
		out->length = len_secs * 1000;

	int offset = (h.author [0] < ' ' || unsigned (h.author [0] - '0') <= 9);
	Gme_File::copy_field_( out->author, &h.author [offset], sizeof h.author - offset );

	GME_COPY_FIELD( h, out, song );
	GME_COPY_FIELD( h, out, game );
	GME_COPY_FIELD( h, out, dumper );
	GME_COPY_FIELD( h, out, comment );

	if ( xid6_size )
		get_spc_xid6( xid6, xid6_size, out );
}

blargg_err_t Spc_Emu::track_info_( track_info_t* out, int ) const
{
	get_spc_info( header(), trailer(), trailer_size(), out );
	return 0;
}

static blargg_err_t check_spc_header( void const* header )
{
	if ( memcmp( header, "SNES-SPC700 Sound File Data", 27 ) )
		return gme_wrong_file_type;
	return 0;
}

struct Spc_File : Gme_Info_
{
	Spc_Emu::header_t header;
	blargg_vector<byte> xid6;

	Spc_File() { set_type( gme_spc_type ); }

	blargg_err_t load_( Data_Reader& in )
	{
		long file_size = in.remain();
		if ( file_size < Snes_Spc::spc_min_file_size )
			return gme_wrong_file_type;
		RETURN_ERR( in.read( &header, Spc_Emu::header_size ) );
		RETURN_ERR( check_spc_header( header.tag ) );
		long const xid6_offset = 0x10200;
		long xid6_size = file_size - xid6_offset;
		if ( xid6_size > 0 )
		{
			RETURN_ERR( xid6.resize( xid6_size ) );
			RETURN_ERR( in.skip( xid6_offset - Spc_Emu::header_size ) );
			RETURN_ERR( in.read( xid6.begin(), xid6.size() ) );
		}
		return 0;
	}

	blargg_err_t track_info_( track_info_t* out, int ) const
	{
		get_spc_info( header, xid6.begin(), xid6.size(), out );
		return 0;
	}
};

static Music_Emu* new_spc_emu () { return BLARGG_NEW Spc_Emu ; }
static Music_Emu* new_spc_file() { return BLARGG_NEW Spc_File; }

static gme_type_t_ const gme_spc_type_ = { "Super Nintendo", 1, &new_spc_emu, &new_spc_file, "SPC", 0 };
BLARGG_EXPORT extern gme_type_t const gme_spc_type = &gme_spc_type_;

// Setup

blargg_err_t Spc_Emu::set_sample_rate_( long sample_rate )
{
	RETURN_ERR( apu.init() );
	enable_accuracy( false );
	if ( sample_rate != native_sample_rate )
	{
		RETURN_ERR( resampler.buffer_size( native_sample_rate / 20 * 2 ) );
		resampler.time_ratio( (double) native_sample_rate / sample_rate, 0.9965 );
	}
	return 0;
}

void Spc_Emu::enable_accuracy_( bool b )
{
	Music_Emu::enable_accuracy_( b );
	filter.enable( b );
}

void Spc_Emu::mute_voices_( int m )
{
	Music_Emu::mute_voices_( m );
	apu.mute_voices( m );
}

blargg_err_t Spc_Emu::load_mem_( byte const* in, long size )
{
	assert( offsetof (header_t,unused2 [46]) == header_size );
	file_data = in;
	file_size = size;
	set_voice_count( Snes_Spc::voice_count );
	if ( size < Snes_Spc::spc_min_file_size )
		return gme_wrong_file_type;
	return check_spc_header( in );
}

// Emulation

void Spc_Emu::set_tempo_( double t )
{
	apu.set_tempo( (int) (t * apu.tempo_unit) );
}

blargg_err_t Spc_Emu::start_track_( int track )
{
	RETURN_ERR( Music_Emu::start_track_( track ) );
	resampler.clear();
	filter.clear();
	RETURN_ERR( apu.load_spc( file_data, file_size ) );
	filter.set_gain( (int) (gain() * SPC_Filter::gain_unit) );
	apu.clear_echo();
	track_info_t spc_info;
	RETURN_ERR( track_info_( &spc_info, track ) );
	// Set a default track length, need a non-zero fadeout
	if ( spc_info.length > 0 )
		set_fade ( spc_info.length, 50 );
	return 0;
}

blargg_err_t Spc_Emu::play_and_filter( long count, sample_t out [] )
{
	RETURN_ERR( apu.play( count, out ) );
	filter.run( out, count );
	return 0;
}

blargg_err_t Spc_Emu::skip_( long count )
{
	if ( sample_rate() != native_sample_rate )
	{
		count = long (count * resampler.ratio()) & ~1;
		count -= resampler.skip_input( count );
	}

	// TODO: shouldn't skip be adjusted for the 64 samples read afterwards?

	if ( count > 0 )
	{
		RETURN_ERR( apu.skip( count ) );
		filter.clear();
	}

	// eliminate pop due to resampler
	const int resampler_latency = 64;
	sample_t buf [resampler_latency];
	return play_( resampler_latency, buf );
}

blargg_err_t Spc_Emu::play_( long count, sample_t* out )
{
	if ( sample_rate() == native_sample_rate )
		return play_and_filter( count, out );

	long remain = count;
	while ( remain > 0 )
	{
		remain -= resampler.read( &out [count - remain], remain );
		if ( remain > 0 )
		{
			long n = resampler.max_write();
			RETURN_ERR( play_and_filter( n, resampler.buffer() ) );
			resampler.write( n );
		}
	}
	check( remain == 0 );
	return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <chrono>
#include <thread>
#include <numeric>

#include <libdariadb/timeutil.h>
#include <libdariadb/engine.h>
#include <libdariadb/meas.h>
#include <libdariadb/utils/logger.h>
#include <libdariadb/utils/locker.h>
#include <libclient/client.h>
#include <libserver/server.h>

#include <boost/program_options.hpp>

using namespace dariadb;
using namespace dariadb::storage;

namespace po = boost::program_options;

std::string storage_path = "dariadb_storage";

unsigned short server_port = 2001;
std::string server_host = "127.0.0.1";
bool run_server_flag = true;
size_t server_threads_count = dariadb::net::SERVER_IO_THREADS_DEFAULT;
STRATEGY strategy = STRATEGY::FAST_WRITE;
Time cap_store_period = 0;
size_t clients_count = 5;
bool dont_clean=false;
Engine* engine = nullptr;
dariadb::net::Server*server_instance = nullptr;

void run_server() {

	bool is_exists = false;
	if (dariadb::utils::fs::path_exists(storage_path)) {

        if(!dont_clean){
            std::cout<<"remove old storage..."<<std::endl;
            dariadb::utils::fs::rm(storage_path);
        }else{
            is_exists = true;
        }
	}

	if (is_exists) {
		Options::start(storage_path);
	}
	else {
		Options::start();
	}
	Options::instance()->cap_store_period = cap_store_period;
	Options::instance()->strategy = strategy;
	Options::instance()->path = storage_path;
	Options::instance()->aof_max_size = Options::instance()->measurements_count();

	engine = new Engine();

	if (!is_exists) {
		Options::instance()->save();
	}

	dariadb::net::Server::Param server_param(server_port, server_threads_count);
	server_instance=new dariadb::net::Server(server_param);
	server_instance->set_storage(engine);

	server_instance->start();

	while (!server_instance->is_runned()) {
	}
}

const size_t MEASES_SIZE = 2000;
const size_t SEND_COUNT = 200;

std::vector<float> elapsed;
std::vector<std::thread> threads;
std::vector<dariadb::net::client::Client_Ptr> clients;

void write_thread(dariadb::net::client::Client_Ptr client, size_t thread_num) {
	dariadb::MeasArray ma;
	ma.resize(MEASES_SIZE);
	for (size_t i = 0; i < MEASES_SIZE; ++i) {
		ma[i].id = dariadb::Id(i);
		ma[i].value = dariadb::Value(i);
		ma[i].time = i;
	}

    auto start = clock();
	for(size_t i=0;i<SEND_COUNT;++i){
		client->append(ma);
	}
    auto el = (((float)clock() - start) / CLOCKS_PER_SEC);
    elapsed[thread_num]=el;
}

int main(int argc,char**argv){
	po::options_description desc("Allowed options");
	desc.add_options()
		("help", "produce help message")
		("storage-path", po::value<std::string>(&storage_path)->default_value(storage_path), "path to storage.")
		("port", po::value<unsigned short>(&server_port)->default_value(server_port), "server port.")
		("server-host", po::value<std::string>(&server_host)->default_value(server_host), "server host.")
        ("io-threads", po::value<size_t>(&server_threads_count)->default_value(server_threads_count), "server threads for query processing.")
		("strategy", po::value<STRATEGY>(&strategy)->default_value(strategy),"write strategy.")
		("store-period",po::value<Time>(&cap_store_period)->default_value(cap_store_period), "store period in CAP level.")
		("clients-count", po::value<size_t>(&clients_count)->default_value(clients_count), "clients count.")
        ("dont-clean", po::value<bool>(&dont_clean)->default_value(dont_clean), "dont clean folder with storage if exists.")
		("extern-server", "dont run server.");

	po::variables_map vm;
	try {
		po::store(po::parse_command_line(argc, argv, desc), vm);
	}
	catch (std::exception &ex) {
		dariadb::logger("Error: ", ex.what());
		exit(1);
	}
	po::notify(vm);

	if (vm.count("help")) {
		std::cout << desc << std::endl;
		std::exit(0);
	}
	if (vm.count("extern-server")) {
		run_server_flag = false;
	}

    elapsed.resize(clients_count);
    threads.resize(clients_count);
    clients.resize(clients_count);

	if (run_server_flag) {
		run_server();
	}

	dariadb::net::client::Client::Param p(server_host, server_port);

	for (size_t i = 0; i < clients_count; ++i) {
        clients[i]=dariadb::net::client::Client_Ptr{ new dariadb::net::client::Client(p) };
        clients[i]->connect();
	}

	auto start = clock();

	for (size_t i = 0; i < clients_count; ++i) {
        auto t=std::thread{ write_thread, clients[i], i };
        threads[i] = std::move(t);
	}

	for (size_t i = 0; i < clients_count; ++i) {
		threads[i].join();
		clients[i]->disconnect();
		while (clients[i]->state() != dariadb::net::ClientState::DISCONNECTED) {
			std::this_thread::yield();
		}
	}
    auto total_elapsed = (((float)clock() - start) / CLOCKS_PER_SEC);

	if(run_server_flag){
		server_instance->stop();

		while (server_instance->is_runned()) {
			std::this_thread::yield();
		}

		delete engine;
	}

    auto count_per_thread=MEASES_SIZE*SEND_COUNT;
    auto total_writed = count_per_thread*clients_count;
	std::cout << "writed: " << total_writed << std::endl;
    std::cout << "total write time: " << total_elapsed << std::endl;
    std::cout << "total speed: " << total_writed /total_elapsed<<" per sec." << std::endl;

    auto average_time=std::accumulate(elapsed.begin(),elapsed.end(),0.0)/clients_count;
    std::cout << "average time: " << average_time<<" sec." << std::endl;
    std::cout << "average speed: " << count_per_thread/(float)(average_time)<<" per sec." << std::endl;
}
<commit_msg>net_bench: refact.<commit_after>#include <iostream>
#include <chrono>
#include <thread>
#include <numeric>

#include <libdariadb/timeutil.h>
#include <libdariadb/engine.h>
#include <libdariadb/meas.h>
#include <libdariadb/utils/logger.h>
#include <libdariadb/utils/locker.h>
#include <libclient/client.h>
#include <libserver/server.h>

#include <boost/program_options.hpp>

using namespace dariadb;
using namespace dariadb::storage;

namespace po = boost::program_options;

std::string storage_path = "dariadb_storage";

unsigned short server_port = 2001;
std::string server_host = "127.0.0.1";
bool run_server_flag = true;
size_t server_threads_count = dariadb::net::SERVER_IO_THREADS_DEFAULT;
STRATEGY strategy = STRATEGY::FAST_WRITE;
Time cap_store_period = 0;
size_t clients_count = 5;
bool dont_clean=false;
Engine* engine = nullptr;
dariadb::net::Server*server_instance = nullptr;

void run_server() {

	bool is_exists = false;
	if (dariadb::utils::fs::path_exists(storage_path)) {

        if(!dont_clean){
            std::cout<<"remove old storage..."<<std::endl;
            dariadb::utils::fs::rm(storage_path);
        }else{
            is_exists = true;
        }
	}

	if (is_exists) {
		Options::start(storage_path);
	}
	else {
		Options::start();
	}
	Options::instance()->cap_store_period = cap_store_period;
	Options::instance()->strategy = strategy;
	Options::instance()->path = storage_path;
	Options::instance()->aof_max_size = Options::instance()->measurements_count();

	engine = new Engine();

	if (!is_exists) {
		Options::instance()->save();
	}

	dariadb::net::Server::Param server_param(server_port, server_threads_count);
	server_instance=new dariadb::net::Server(server_param);
	server_instance->set_storage(engine);

	server_instance->start();

	while (!server_instance->is_runned()) {
	}
}

const size_t MEASES_SIZE = 2000;
const size_t SEND_COUNT = 200;

std::vector<float> elapsed;
std::vector<std::thread> threads;
std::vector<dariadb::net::client::Client_Ptr> clients;

void write_thread(dariadb::net::client::Client_Ptr client, size_t thread_num) {
	dariadb::MeasArray ma;
	ma.resize(MEASES_SIZE);
	for (size_t i = 0; i < MEASES_SIZE; ++i) {
        ma[i].id = dariadb::Id(thread_num);
		ma[i].value = dariadb::Value(i);
		ma[i].time = i;
	}

    auto start = clock();
	for(size_t i=0;i<SEND_COUNT;++i){
		client->append(ma);
	}
    auto el = (((float)clock() - start) / CLOCKS_PER_SEC);
    elapsed[thread_num]=el;
}

int main(int argc,char**argv){
	po::options_description desc("Allowed options");
	desc.add_options()
		("help", "produce help message")
		("storage-path", po::value<std::string>(&storage_path)->default_value(storage_path), "path to storage.")
		("port", po::value<unsigned short>(&server_port)->default_value(server_port), "server port.")
		("server-host", po::value<std::string>(&server_host)->default_value(server_host), "server host.")
        ("io-threads", po::value<size_t>(&server_threads_count)->default_value(server_threads_count), "server threads for query processing.")
		("strategy", po::value<STRATEGY>(&strategy)->default_value(strategy),"write strategy.")
		("store-period",po::value<Time>(&cap_store_period)->default_value(cap_store_period), "store period in CAP level.")
		("clients-count", po::value<size_t>(&clients_count)->default_value(clients_count), "clients count.")
        ("dont-clean", po::value<bool>(&dont_clean)->default_value(dont_clean), "dont clean folder with storage if exists.")
		("extern-server", "dont run server.");

	po::variables_map vm;
	try {
		po::store(po::parse_command_line(argc, argv, desc), vm);
	}
	catch (std::exception &ex) {
		dariadb::logger("Error: ", ex.what());
		exit(1);
	}
	po::notify(vm);

	if (vm.count("help")) {
		std::cout << desc << std::endl;
		std::exit(0);
	}
	if (vm.count("extern-server")) {
		run_server_flag = false;
	}

    elapsed.resize(clients_count);
    threads.resize(clients_count);
    clients.resize(clients_count);

	if (run_server_flag) {
		run_server();
	}

	dariadb::net::client::Client::Param p(server_host, server_port);

	for (size_t i = 0; i < clients_count; ++i) {
        clients[i]=dariadb::net::client::Client_Ptr{ new dariadb::net::client::Client(p) };
        clients[i]->connect();
	}

    for (size_t i = 0; i < clients_count; ++i) {
        auto t=std::thread{ write_thread, clients[i], i };
        threads[i] = std::move(t);
	}

	for (size_t i = 0; i < clients_count; ++i) {
		threads[i].join();
		clients[i]->disconnect();
		while (clients[i]->state() != dariadb::net::ClientState::DISCONNECTED) {
			std::this_thread::yield();
		}
	}
    dariadb::net::client::Client_Ptr c{ new dariadb::net::client::Client(p) };
    c->connect();
    dariadb::storage::QueryInterval ri(dariadb::IdArray{0},0,0,MEASES_SIZE);
    auto result=c->readInterval(ri);

	if(run_server_flag){
		server_instance->stop();

		while (server_instance->is_runned()) {
			std::this_thread::yield();
		}

		delete engine;
	}

    auto count_per_thread=MEASES_SIZE*SEND_COUNT;
    auto total_writed = count_per_thread*clients_count;
	std::cout << "writed: " << total_writed << std::endl;

    auto average_time=std::accumulate(elapsed.begin(),elapsed.end(),0.0)/clients_count;
    std::cout << "average time: " << average_time<<" sec." << std::endl;
    std::cout << "average speed: " << count_per_thread/(float)(average_time)<<" per sec." << std::endl;

    std::cout<<"result:"<<result.size();

    if(result.size()!=MEASES_SIZE*SEND_COUNT ){
        THROW_EXCEPTION("result.size()!=MEASES_SIZE*SEND_COUNT: ", result.size());
    }
}
<|endoftext|>


<commit_before>// HandleLeak.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "HandleLeak.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// The one and only application object

CWinApp theApp;

using namespace std;

void TestHandleLeak()
{
	cout << __FUNCTION__ << endl;

	SHELLEXECUTEINFO ShExecInfo = {0};
	ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
	ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
	ShExecInfo.hwnd = NULL;
	ShExecInfo.lpVerb = _T("open");
	ShExecInfo.lpFile = _T("cmd");
	ShExecInfo.lpParameters = _T("/c echo 111");
	ShExecInfo.lpDirectory = NULL;
	ShExecInfo.nShow = SW_HIDE;
	ShExecInfo.hInstApp = NULL;

	ShellExecuteEx(&ShExecInfo);

	WaitForSingleObject(ShExecInfo.hProcess,INFINITE);

	return;
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int nRetCode = 0;

	HMODULE hModule = ::GetModuleHandle(NULL);

	if (hModule != NULL)
	{
		// initialize MFC and print and error on failure
		if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
		{
			// TODO: change error code to suit your needs
			_tprintf(_T("Fatal Error: MFC initialization failed\n"));
			nRetCode = 1;
		}
		else
		{
			// TODO: code your application's behavior here.
			int i = 0;
			while (i < 10000)
			{
				TestHandleLeak();
				Sleep(10);
			}
		}
	}
	else
	{
		// TODO: change error code to suit your needs
		_tprintf(_T("Fatal Error: GetModuleHandle failed\n"));
		nRetCode = 1;
	}

	return nRetCode;
}
<commit_msg>close handle<commit_after>// HandleLeak.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "HandleLeak.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// The one and only application object

CWinApp theApp;

using namespace std;

void TestHandleLeak()
{
	cout << __FUNCTION__ << endl;

	SHELLEXECUTEINFO ShExecInfo = {0};
	ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
	ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
	ShExecInfo.hwnd = NULL;
	ShExecInfo.lpVerb = _T("open");
	ShExecInfo.lpFile = _T("cmd");
	ShExecInfo.lpParameters = _T("/c echo 111");
	ShExecInfo.lpDirectory = NULL;
	ShExecInfo.nShow = SW_HIDE;
	ShExecInfo.hInstApp = NULL;

	ShellExecuteEx(&ShExecInfo);

	WaitForSingleObject(ShExecInfo.hProcess,INFINITE);

	CloseHandle(ShExecInfo.hProcess);

	return;
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int nRetCode = 0;

	HMODULE hModule = ::GetModuleHandle(NULL);

	if (hModule != NULL)
	{
		// initialize MFC and print and error on failure
		if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
		{
			// TODO: change error code to suit your needs
			_tprintf(_T("Fatal Error: MFC initialization failed\n"));
			nRetCode = 1;
		}
		else
		{
			// TODO: code your application's behavior here.
			int i = 0;
			while (i < 10000)
			{
				TestHandleLeak();
			}
		}
	}
	else
	{
		// TODO: change error code to suit your needs
		_tprintf(_T("Fatal Error: GetModuleHandle failed\n"));
		nRetCode = 1;
	}

	return nRetCode;
}
<|endoftext|>


<commit_before>
#include "FlareSpacecraftDockingSystem.h"
#include "../../Flare.h"

#include "../FlareStationDock.h"
#include "../FlareStationConnector.h"
#include "../FlareSpacecraft.h"
#include "../../Game/FlareGame.h"
#include "../../Quests/FlareQuestManager.h"

DECLARE_CYCLE_STAT(TEXT("FlareDockingSystem Tick"), STAT_FlareDockingSystem_Tick, STATGROUP_Flare);

#define LOCTEXT_NAMESPACE "FlareDockingSystem"

/*----------------------------------------------------
	Constructor
----------------------------------------------------*/

UFlareSpacecraftDockingSystem::UFlareSpacecraftDockingSystem(const class FObjectInitializer& PCIP)
	: Super(PCIP)
	, Spacecraft(NULL)
{
	SCOPE_CYCLE_COUNTER(STAT_FlareDockingSystem_Tick);
}

/*----------------------------------------------------
	Gameplay events
----------------------------------------------------*/

void UFlareSpacecraftDockingSystem::TickSystem(float DeltaSeconds)
{
}

void UFlareSpacecraftDockingSystem::Initialize(AFlareSpacecraft* OwnerSpacecraft, FFlareSpacecraftSave* OwnerData)
{
	Spacecraft = OwnerSpacecraft;
	Components = Spacecraft->GetComponentsByClass(UFlareSpacecraftComponent::StaticClass());
	Description = Spacecraft->GetParent()->GetDescription();
	Data = OwnerData;

}

void UFlareSpacecraftDockingSystem::Start()
{
	// Dock data
	int32 DockCount = 0;
	int32 ConnectorCount = 0;
	TArray<UActorComponent*> ActorComponents;
	Spacecraft->GetComponents(ActorComponents);

	for (TArray<UActorComponent*>::TIterator ComponentIt(ActorComponents); ComponentIt; ++ComponentIt)
	{
		FVector DockLocation;
		FRotator DockRotation;
		UFlareStationDock* DockComponent = Cast<UFlareStationDock>(*ComponentIt);
		UFlareStationConnector* ConnectorComponent = Cast<UFlareStationConnector>(*ComponentIt);

		// Fill dock slots
		if (DockComponent)
		{
			DockComponent->GetSocketWorldLocationAndRotation(FName("dock"), DockLocation, DockRotation);

			// Fill info
			FFlareDockingInfo Info;
			Info.Ship = NULL;
			Info.LocalAxis = Spacecraft->Airframe->GetComponentToWorld().Inverse().GetRotation().RotateVector(DockRotation.RotateVector(FVector(1,0,0)));
			Info.LocalTopAxis = Spacecraft->Airframe->GetComponentToWorld().Inverse().GetRotation().RotateVector(DockRotation.RotateVector(FVector(0,1,0)));
			Info.LocalLocation = Spacecraft->Airframe->GetComponentToWorld().Inverse().TransformPosition(DockLocation);
			Info.DockId = DockCount;
			Info.DockSize = DockComponent->DockSize;
			Info.Station = Spacecraft;
			Info.Granted = false;
			Info.Occupied = false;

			// Push this slot
			DockingSlots.Add(Info);
			DockCount++;
		}

		// Fill connector data to the parent
		if (ConnectorComponent)
		{
			FCHECK(ConnectorCount < Spacecraft->GetDescription()->StationConnectorCount);
			FCHECK(ConnectorCount < Spacecraft->GetParent()->GetStationConnectors().Num());

			// Fetch connector data
			FFlareDockingInfo* StationConnection = Spacecraft->GetParent()->GetStationConnector(ConnectorComponent->SlotIdentifier);
			FCHECK(StationConnection != NULL);

			// Fill info
			if (StationConnection)
			{
				ConnectorComponent->GetSocketWorldLocationAndRotation(FName("dock"), DockLocation, DockRotation);

				StationConnection->Ship = NULL;
				StationConnection->Station = Spacecraft;
				StationConnection->LocalAxis = Spacecraft->Airframe->GetComponentToWorld().Inverse().GetRotation().RotateVector(DockRotation.RotateVector(FVector(1, 0, 0)));
				StationConnection->LocalTopAxis = Spacecraft->Airframe->GetComponentToWorld().Inverse().GetRotation().RotateVector(DockRotation.RotateVector(FVector(0, 1, 0)));
				StationConnection->LocalLocation = Spacecraft->Airframe->GetComponentToWorld().Inverse().TransformPosition(DockLocation);
				StationConnection->Occupied = true;
			}
			else
			{
				FLOGV("UFlareSpacecraftDockingSystem::Start : couldn't find station connector '%s' in parent", *ConnectorComponent->SlotIdentifier.ToString());
			}

			ConnectorCount++;
		}
	}
}

bool UFlareSpacecraftDockingSystem::HasCompatibleDock(AFlareSpacecraft* Ship) const
{
	for (int32 i = 0; i < DockingSlots.Num(); i++)
	{
		if (DockingSlots[i].DockSize == Ship->GetSize())
		{
			return true;
		}
	}
	return false;
}

FFlareDockingInfo UFlareSpacecraftDockingSystem::RequestDock(AFlareSpacecraft* Ship, FVector PreferredLocation)
{
	int32 BestIndex = -1;
	float BestDistance = 0;

	// Player docking data
	FText PlayerDockInfo;
	AFlareSpacecraft* PlayerDockSpacecraft;
	FFlareDockingParameters PlayerDockingParameters;
	AFlareSpacecraft* PlayerShip = Ship->GetGame()->GetPC()->GetShipPawn();

	// Deny all docking requests if the player is docking
	if (PlayerShip)
	{
		bool DockingInProgress = PlayerShip->GetManualDockingProgress(PlayerDockSpacecraft, PlayerDockingParameters, PlayerDockInfo);
		if (DockingInProgress && PlayerDockSpacecraft == Spacecraft && PlayerShip != Ship)
		{
			FLOG("UFlareSpacecraftDockingSystem::RequestDock : denied, player is docking");
			FFlareDockingInfo Info;
			Info.Granted = false;
			Info.Station = Spacecraft;
			return Info;
		}
	}

	// Looking for nearest available slot
	for (int32 i = 0; i < DockingSlots.Num(); i++)
	{
		if (!DockingSlots[i].Granted && DockingSlots[i].DockSize == Ship->GetSize())
		{
			float DockDistance = (Spacecraft->Airframe->GetComponentToWorld().TransformPosition(DockingSlots[i].LocalLocation) - PreferredLocation).Size();
			if (BestIndex < 0 || DockDistance < BestDistance)
			{
				BestDistance = DockDistance;
				BestIndex = i;
			}
		}
	}

	// Granted
	if (BestIndex >= 0)
	{
		DockingSlots[BestIndex].Granted = true;
		DockingSlots[BestIndex].Ship = Ship;
		return DockingSlots[BestIndex];
	}

	// Denied, but player ship, so undock an AI ship
	else if (Ship->IsPlayerShip())
	{
		BestIndex = 0;

		// Look again without constraint
		for (int32 i = 0; i < DockingSlots.Num(); i++)
		{
			if (DockingSlots[i].DockSize == Ship->GetSize())
			{
				float DockDistance = (Spacecraft->Airframe->GetComponentToWorld().TransformPosition(DockingSlots[i].LocalLocation) - PreferredLocation).Size();
				if (BestIndex < 0 || DockDistance < BestDistance)
				{
					BestDistance = DockDistance;
					BestIndex = i;
				}
			}
		}

		// Undock previous owner
		if ((DockingSlots[BestIndex].Granted || DockingSlots[BestIndex].Occupied) && DockingSlots[BestIndex].Ship && DockingSlots[BestIndex].Ship->IsValidLowLevel())
		{
			if (DockingSlots[BestIndex].Ship->GetNavigationSystem()->IsDocked())
			{
				DockingSlots[BestIndex].Ship->GetNavigationSystem()->Undock();
			}
			else
			{
				DockingSlots[BestIndex].Ship->GetNavigationSystem()->AbortAllCommands();
			}
		}

		// Grant dock
		DockingSlots[BestIndex].Granted = true;
		DockingSlots[BestIndex].Ship = Ship;
		return DockingSlots[BestIndex];
	}

	// Denied
	else
	{
		FFlareDockingInfo Info;
		Info.Granted = false;
		Info.Station = Spacecraft;
		return Info;
	}
}

void UFlareSpacecraftDockingSystem::ReleaseDock(AFlareSpacecraft* Ship, int32 DockId)
{
	FLOGV("UFlareSpacecraftDockingSystem::ReleaseDock %d ('%s')", DockId, *Ship->GetParent()->GetImmatriculation().ToString());
	DockingSlots[DockId].Granted = false;
	DockingSlots[DockId].Occupied = false;
	DockingSlots[DockId].Ship = NULL;
}

void UFlareSpacecraftDockingSystem::Dock(AFlareSpacecraft* Ship, int32 DockId)
{
	FLOGV("UFlareSpacecraftDockingSystem::Dock %d ('%s')", DockId, *Ship->GetParent()->GetImmatriculation().ToString());
	DockingSlots[DockId].Granted = true;
	DockingSlots[DockId].Occupied = true;
	DockingSlots[DockId].Ship = Ship;

	Spacecraft->GetGame()->GetQuestManager()->OnShipDocked(Spacecraft->GetParent(), Ship->GetParent());
}

TArray<AFlareSpacecraft*> UFlareSpacecraftDockingSystem::GetDockedShips()
{
	TArray<AFlareSpacecraft*> Result;

	for (int32 i = 0; i < DockingSlots.Num(); i++)
	{
		if (DockingSlots[i].Granted && DockingSlots[i].Occupied)
		{
			//FLOGV("UFlareSpacecraftDockingSystem::GetDockedShips : found valid dock %d", i);
			Result.AddUnique(DockingSlots[i].Ship);
		}
	}

	return Result;
}

bool UFlareSpacecraftDockingSystem::HasAvailableDock(AFlareSpacecraft* Ship) const
{
	// Looking for slot
	for (int32 i = 0; i < DockingSlots.Num(); i++)
	{
		if (DockingSlots[i].DockSize != Ship->GetSize())
		{
			continue;
		}

		if (!DockingSlots[i].Granted)
		{
			return true;
		}
	}

	return false;
}

int UFlareSpacecraftDockingSystem::GetDockCount() const
{
	return DockingSlots.Num();
}

FFlareDockingInfo UFlareSpacecraftDockingSystem::GetDockInfo(int32 DockId)
{
	return DockingSlots[DockId];
}

bool UFlareSpacecraftDockingSystem::IsGrantedShip(AFlareSpacecraft* ShipCanditate) const
{
	for (int32 i = 0; i < DockingSlots.Num(); i++)
	{
		if (DockingSlots[i].Granted && DockingSlots[i].Ship == ShipCanditate)
		{
			return true;
		}
	}

	return false;
}

bool UFlareSpacecraftDockingSystem::IsDockedShip(AFlareSpacecraft* ShipCanditate) const
{
	for (int32 i = 0; i < DockingSlots.Num(); i++)
	{
		if (DockingSlots[i].Occupied && DockingSlots[i].Ship == ShipCanditate)
		{
			return true;
		}
	}

	return false;
}

#undef LOCTEXT_NAMESPACE
<commit_msg>#1035 Fix complex guest orientation<commit_after>
#include "FlareSpacecraftDockingSystem.h"
#include "../../Flare.h"

#include "../FlareStationDock.h"
#include "../FlareStationConnector.h"
#include "../FlareSpacecraft.h"
#include "../../Game/FlareGame.h"
#include "../../Quests/FlareQuestManager.h"

DECLARE_CYCLE_STAT(TEXT("FlareDockingSystem Tick"), STAT_FlareDockingSystem_Tick, STATGROUP_Flare);

#define LOCTEXT_NAMESPACE "FlareDockingSystem"

/*----------------------------------------------------
	Constructor
----------------------------------------------------*/

UFlareSpacecraftDockingSystem::UFlareSpacecraftDockingSystem(const class FObjectInitializer& PCIP)
	: Super(PCIP)
	, Spacecraft(NULL)
{
	SCOPE_CYCLE_COUNTER(STAT_FlareDockingSystem_Tick);
}

/*----------------------------------------------------
	Gameplay events
----------------------------------------------------*/

void UFlareSpacecraftDockingSystem::TickSystem(float DeltaSeconds)
{
}

void UFlareSpacecraftDockingSystem::Initialize(AFlareSpacecraft* OwnerSpacecraft, FFlareSpacecraftSave* OwnerData)
{
	Spacecraft = OwnerSpacecraft;
	Components = Spacecraft->GetComponentsByClass(UFlareSpacecraftComponent::StaticClass());
	Description = Spacecraft->GetParent()->GetDescription();
	Data = OwnerData;

}

void UFlareSpacecraftDockingSystem::Start()
{
	// Dock data
	int32 DockCount = 0;
	int32 ConnectorCount = 0;
	TArray<UActorComponent*> ActorComponents;
	Spacecraft->GetComponents(ActorComponents);

	for (TArray<UActorComponent*>::TIterator ComponentIt(ActorComponents); ComponentIt; ++ComponentIt)
	{
		FVector DockLocation;
		FRotator DockRotation;
		UFlareStationDock* DockComponent = Cast<UFlareStationDock>(*ComponentIt);
		UFlareStationConnector* ConnectorComponent = Cast<UFlareStationConnector>(*ComponentIt);

		// Fill dock slots
		if (DockComponent)
		{
			DockComponent->GetSocketWorldLocationAndRotation(FName("dock"), DockLocation, DockRotation);

			// Fill info
			FFlareDockingInfo Info;
			Info.Ship = NULL;
			Info.LocalAxis = Spacecraft->Airframe->GetComponentToWorld().Inverse().GetRotation().RotateVector(DockRotation.RotateVector(FVector(1,0,0)));
			Info.LocalTopAxis = Spacecraft->Airframe->GetComponentToWorld().Inverse().GetRotation().RotateVector(DockRotation.RotateVector(FVector(0,1,0)));
			Info.LocalLocation = Spacecraft->Airframe->GetComponentToWorld().Inverse().TransformPosition(DockLocation);
			Info.DockId = DockCount;
			Info.DockSize = DockComponent->DockSize;
			Info.Station = Spacecraft;
			Info.Granted = false;
			Info.Occupied = false;

			// Push this slot
			DockingSlots.Add(Info);
			DockCount++;
		}

		// Fill connector data to the parent
		if (ConnectorComponent)
		{
			FCHECK(ConnectorCount < Spacecraft->GetDescription()->StationConnectorCount);
			FCHECK(ConnectorCount < Spacecraft->GetParent()->GetStationConnectors().Num());

			// Fetch connector data
			FFlareDockingInfo* StationConnection = Spacecraft->GetParent()->GetStationConnector(ConnectorComponent->SlotIdentifier);
			FCHECK(StationConnection != NULL);

			// Fill info
			if (StationConnection)
			{
				ConnectorComponent->GetSocketWorldLocationAndRotation(FName("dock"), DockLocation, DockRotation);

				StationConnection->Ship = NULL;
				StationConnection->Station = Spacecraft;
				StationConnection->LocalAxis = Spacecraft->Airframe->GetComponentToWorld().Inverse().GetRotation().RotateVector(DockRotation.RotateVector(FVector(0, 0, 1)));
				StationConnection->LocalTopAxis = Spacecraft->Airframe->GetComponentToWorld().Inverse().GetRotation().RotateVector(DockRotation.RotateVector(FVector(0, 1, 0)));
				StationConnection->LocalLocation = Spacecraft->Airframe->GetComponentToWorld().Inverse().TransformPosition(DockLocation);
				StationConnection->Occupied = true;
			}
			else
			{
				FLOGV("UFlareSpacecraftDockingSystem::Start : couldn't find station connector '%s' in parent", *ConnectorComponent->SlotIdentifier.ToString());
			}

			ConnectorCount++;
		}
	}
}

bool UFlareSpacecraftDockingSystem::HasCompatibleDock(AFlareSpacecraft* Ship) const
{
	for (int32 i = 0; i < DockingSlots.Num(); i++)
	{
		if (DockingSlots[i].DockSize == Ship->GetSize())
		{
			return true;
		}
	}
	return false;
}

FFlareDockingInfo UFlareSpacecraftDockingSystem::RequestDock(AFlareSpacecraft* Ship, FVector PreferredLocation)
{
	int32 BestIndex = -1;
	float BestDistance = 0;

	// Player docking data
	FText PlayerDockInfo;
	AFlareSpacecraft* PlayerDockSpacecraft;
	FFlareDockingParameters PlayerDockingParameters;
	AFlareSpacecraft* PlayerShip = Ship->GetGame()->GetPC()->GetShipPawn();

	// Deny all docking requests if the player is docking
	if (PlayerShip)
	{
		bool DockingInProgress = PlayerShip->GetManualDockingProgress(PlayerDockSpacecraft, PlayerDockingParameters, PlayerDockInfo);
		if (DockingInProgress && PlayerDockSpacecraft == Spacecraft && PlayerShip != Ship)
		{
			FLOG("UFlareSpacecraftDockingSystem::RequestDock : denied, player is docking");
			FFlareDockingInfo Info;
			Info.Granted = false;
			Info.Station = Spacecraft;
			return Info;
		}
	}

	// Looking for nearest available slot
	for (int32 i = 0; i < DockingSlots.Num(); i++)
	{
		if (!DockingSlots[i].Granted && DockingSlots[i].DockSize == Ship->GetSize())
		{
			float DockDistance = (Spacecraft->Airframe->GetComponentToWorld().TransformPosition(DockingSlots[i].LocalLocation) - PreferredLocation).Size();
			if (BestIndex < 0 || DockDistance < BestDistance)
			{
				BestDistance = DockDistance;
				BestIndex = i;
			}
		}
	}

	// Granted
	if (BestIndex >= 0)
	{
		DockingSlots[BestIndex].Granted = true;
		DockingSlots[BestIndex].Ship = Ship;
		return DockingSlots[BestIndex];
	}

	// Denied, but player ship, so undock an AI ship
	else if (Ship->IsPlayerShip())
	{
		BestIndex = 0;

		// Look again without constraint
		for (int32 i = 0; i < DockingSlots.Num(); i++)
		{
			if (DockingSlots[i].DockSize == Ship->GetSize())
			{
				float DockDistance = (Spacecraft->Airframe->GetComponentToWorld().TransformPosition(DockingSlots[i].LocalLocation) - PreferredLocation).Size();
				if (BestIndex < 0 || DockDistance < BestDistance)
				{
					BestDistance = DockDistance;
					BestIndex = i;
				}
			}
		}

		// Undock previous owner
		if ((DockingSlots[BestIndex].Granted || DockingSlots[BestIndex].Occupied) && DockingSlots[BestIndex].Ship && DockingSlots[BestIndex].Ship->IsValidLowLevel())
		{
			if (DockingSlots[BestIndex].Ship->GetNavigationSystem()->IsDocked())
			{
				DockingSlots[BestIndex].Ship->GetNavigationSystem()->Undock();
			}
			else
			{
				DockingSlots[BestIndex].Ship->GetNavigationSystem()->AbortAllCommands();
			}
		}

		// Grant dock
		DockingSlots[BestIndex].Granted = true;
		DockingSlots[BestIndex].Ship = Ship;
		return DockingSlots[BestIndex];
	}

	// Denied
	else
	{
		FFlareDockingInfo Info;
		Info.Granted = false;
		Info.Station = Spacecraft;
		return Info;
	}
}

void UFlareSpacecraftDockingSystem::ReleaseDock(AFlareSpacecraft* Ship, int32 DockId)
{
	FLOGV("UFlareSpacecraftDockingSystem::ReleaseDock %d ('%s')", DockId, *Ship->GetParent()->GetImmatriculation().ToString());
	DockingSlots[DockId].Granted = false;
	DockingSlots[DockId].Occupied = false;
	DockingSlots[DockId].Ship = NULL;
}

void UFlareSpacecraftDockingSystem::Dock(AFlareSpacecraft* Ship, int32 DockId)
{
	FLOGV("UFlareSpacecraftDockingSystem::Dock %d ('%s')", DockId, *Ship->GetParent()->GetImmatriculation().ToString());
	DockingSlots[DockId].Granted = true;
	DockingSlots[DockId].Occupied = true;
	DockingSlots[DockId].Ship = Ship;

	Spacecraft->GetGame()->GetQuestManager()->OnShipDocked(Spacecraft->GetParent(), Ship->GetParent());
}

TArray<AFlareSpacecraft*> UFlareSpacecraftDockingSystem::GetDockedShips()
{
	TArray<AFlareSpacecraft*> Result;

	for (int32 i = 0; i < DockingSlots.Num(); i++)
	{
		if (DockingSlots[i].Granted && DockingSlots[i].Occupied)
		{
			//FLOGV("UFlareSpacecraftDockingSystem::GetDockedShips : found valid dock %d", i);
			Result.AddUnique(DockingSlots[i].Ship);
		}
	}

	return Result;
}

bool UFlareSpacecraftDockingSystem::HasAvailableDock(AFlareSpacecraft* Ship) const
{
	// Looking for slot
	for (int32 i = 0; i < DockingSlots.Num(); i++)
	{
		if (DockingSlots[i].DockSize != Ship->GetSize())
		{
			continue;
		}

		if (!DockingSlots[i].Granted)
		{
			return true;
		}
	}

	return false;
}

int UFlareSpacecraftDockingSystem::GetDockCount() const
{
	return DockingSlots.Num();
}

FFlareDockingInfo UFlareSpacecraftDockingSystem::GetDockInfo(int32 DockId)
{
	return DockingSlots[DockId];
}

bool UFlareSpacecraftDockingSystem::IsGrantedShip(AFlareSpacecraft* ShipCanditate) const
{
	for (int32 i = 0; i < DockingSlots.Num(); i++)
	{
		if (DockingSlots[i].Granted && DockingSlots[i].Ship == ShipCanditate)
		{
			return true;
		}
	}

	return false;
}

bool UFlareSpacecraftDockingSystem::IsDockedShip(AFlareSpacecraft* ShipCanditate) const
{
	for (int32 i = 0; i < DockingSlots.Num(); i++)
	{
		if (DockingSlots[i].Occupied && DockingSlots[i].Ship == ShipCanditate)
		{
			return true;
		}
	}

	return false;
}

#undef LOCTEXT_NAMESPACE
<|endoftext|>


<commit_before>#include "binary_message.h"

#include "../core/exceptions.hpp"

#include <functional>

namespace nng {

    namespace messaging {

        binary_message::binary_message()
            : message_base()
            , _header()
            , _body() {
        }

        binary_message::binary_message(::nng_msg* msgp)
            : message_base(msgp)
            , _header(msgp)
            , _body(msgp) {
        }

        binary_message::~binary_message() {
            free();
        }

        binary_message::operator std::string() {
            std::string s;
            const auto buf = body()->get();
            for (auto it = buf.begin(); it != buf.end(); it++) {
                s.push_back(((std::string::value_type*)*it)[0]);
            }
            return s;
        }

        binary_message_header* const binary_message::header() {
            return &_header;
        }

        binary_message_body* const binary_message::body() {
            return &_body;
        }

        message_base::size_type binary_message::get_size() const {
            // Should be both (Header.Size + Body.Size).
            return _header.get_size() + _body.get_size();
        }

        void binary_message::clear() {
            _header.clear();
            _body.clear();
        }

        void binary_message::set_msgp(::nng_msg* msgp) {
            // Frees any previously existing internal message beforehand.
            message_base::set_msgp(msgp);
            _header.set_msgp(msgp);
            _body.set_msgp(msgp);
        }

        void binary_message::allocate(size_type sz) {
            if (has_message()) { return; }
            ::nng_msg* msgp;
            const auto errnum = ::nng_msg_alloc(&msgp, sz);
            THROW_NNG_EXCEPTION_EC(errnum);
            binary_message::set_msgp(msgp);
        }

        void binary_message::free() {
            if (!has_message()) { return; }
            ::nng_msg_free(get_msgp());
            binary_message::set_msgp(nullptr);
        }
    }
}
<commit_msg>allocating allows for re-allocation<commit_after>#include "binary_message.h"

#include "../core/exceptions.hpp"

#include <functional>

namespace nng {

    namespace messaging {

        binary_message::binary_message()
            : message_base()
            , _header()
            , _body() {
        }

        binary_message::binary_message(::nng_msg* msgp)
            : message_base(msgp)
            , _header(msgp)
            , _body(msgp) {
        }

        binary_message::~binary_message() {
            free();
        }

        binary_message::operator std::string() {
            std::string s;
            const auto buf = body()->get();
            for (auto it = buf.begin(); it != buf.end(); it++) {
                s.push_back(((std::string::value_type*)*it)[0]);
            }
            return s;
        }

        binary_message_header* const binary_message::header() {
            return &_header;
        }

        binary_message_body* const binary_message::body() {
            return &_body;
        }

        message_base::size_type binary_message::get_size() const {
            // Should be both (Header.Size + Body.Size).
            return _header.get_size() + _body.get_size();
        }

        void binary_message::clear() {
            _header.clear();
            _body.clear();
        }

        void binary_message::set_msgp(::nng_msg* msgp) {
            // Frees any previously existing internal message beforehand.
            message_base::set_msgp(msgp);
            _header.set_msgp(msgp);
            _body.set_msgp(msgp);
        }

        void binary_message::allocate(size_type sz) {
            if (has_message()) { free(); }
            ::nng_msg* msgp;
            const auto errnum = ::nng_msg_alloc(&msgp, sz);
            THROW_NNG_EXCEPTION_EC(errnum);
            binary_message::set_msgp(msgp);
        }

        void binary_message::free() {
            if (!has_message()) { return; }
            ::nng_msg_free(get_msgp());
            binary_message::set_msgp(nullptr);
        }
    }
}
<|endoftext|>