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

#include "SkBBoxRecord.h"

void SkBBoxRecord::drawOval(const SkRect& rect, const SkPaint& paint) {
    if (this->transformBounds(rect, &paint)) {
        INHERITED::drawOval(rect, paint);
    }
}

void SkBBoxRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
    if (this->transformBounds(rrect.rect(), &paint)) {
        INHERITED::drawRRect(rrect, paint);
    }
}

void SkBBoxRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
    if (this->transformBounds(rect, &paint)) {
        INHERITED::drawRect(rect, paint);
    }
}

void SkBBoxRecord::drawPath(const SkPath& path, const SkPaint& paint) {
    if (path.isInverseFillType()) {
        // If path is inverse filled, use the current clip bounds as the
        // path's device-space bounding box.
        SkIRect clipBounds;
        if (this->getClipDeviceBounds(&clipBounds)) {
            this->handleBBox(SkRect::MakeFromIRect(clipBounds));
            INHERITED::drawPath(path, paint);
        }
    } else if (this->transformBounds(path.getBounds(), &paint)) {
        INHERITED::drawPath(path, paint);
    }
}

void SkBBoxRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
                              const SkPaint& paint) {
    SkRect bbox;
    bbox.set(pts, count);
    // Small min width value, just to ensure hairline point bounding boxes aren't empty.
    // Even though we know hairline primitives are drawn one pixel wide, we do not use a
    // minimum of 1 because the playback scale factor is unknown at record time. Later
    // outsets will take care of adding additional padding for antialiasing and rounding out
    // to integer device coordinates, guaranteeing that the rasterized pixels will be included
    // in the computed bounds.
    // Note: The device coordinate outset in SkBBoxHierarchyRecord::handleBBox is currently
    // done in the recording coordinate space, which is wrong.
    // http://code.google.com/p/skia/issues/detail?id=1021
    static const SkScalar kMinWidth = SkFloatToScalar(0.01f);
    SkScalar halfStrokeWidth = SkMaxScalar(paint.getStrokeWidth(), kMinWidth) / 2;
    bbox.outset(halfStrokeWidth, halfStrokeWidth);
    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawPoints(mode, count, pts, paint);
    }
}

void SkBBoxRecord::drawPaint(const SkPaint& paint) {
    SkRect bbox;
    if (this->getClipBounds(&bbox)) {
        if (this->transformBounds(bbox, &paint)) {
            INHERITED::drawPaint(paint);
        }
    }
}

void SkBBoxRecord::clear(SkColor color) {
    SkISize size = this->getDeviceSize();
    SkRect bbox = {0, 0, SkIntToScalar(size.width()), SkIntToScalar(size.height())};
    this->handleBBox(bbox);
    INHERITED::clear(color);
}

void SkBBoxRecord::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
                            const SkPaint& paint) {
    SkRect bbox;
    paint.measureText(text, byteLength, &bbox);
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);

    // Vertical and aligned text need to be offset
    if (paint.isVerticalText()) {
        SkScalar h = bbox.fBottom - bbox.fTop;
        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
            bbox.fTop    -= h / 2;
            bbox.fBottom -= h / 2;
        }
        // Pad top and bottom with max extents from FontMetrics
        bbox.fBottom += metrics.fBottom;
        bbox.fTop += metrics.fTop;
    } else {
        SkScalar w = bbox.fRight - bbox.fLeft;
        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
            bbox.fLeft  -= w / 2;
            bbox.fRight -= w / 2;
        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
            bbox.fLeft  -= w;
            bbox.fRight -= w;
        }
        // Set vertical bounds to max extents from font metrics
        bbox.fTop = metrics.fTop;
        bbox.fBottom = metrics.fBottom;
    }

    // Pad horizontal bounds on each side by half of max vertical extents (this is sort of
    // arbitrary, but seems to produce reasonable results, if there were a way of getting max
    // glyph X-extents to pad by, that may be better here, but FontMetrics fXMin and fXMax seem
    // incorrect on most platforms (too small in Linux, never even set in Windows).
    SkScalar pad = (metrics.fBottom - metrics.fTop) / 2;
    bbox.fLeft  -= pad;
    bbox.fRight += pad;

    bbox.fLeft += x;
    bbox.fRight += x;
    bbox.fTop += y;
    bbox.fBottom += y;
    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawText(text, byteLength, x, y, paint);
    }
}

void SkBBoxRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
                              const SkPaint* paint) {
    SkRect bbox = {left, top, left + bitmap.width(), top + bitmap.height()};
    if (this->transformBounds(bbox, paint)) {
        INHERITED::drawBitmap(bitmap, left, top, paint);
    }
}

void SkBBoxRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
                                  const SkRect& dst, const SkPaint* paint) {
    if (this->transformBounds(dst, paint)) {
        INHERITED::drawBitmapRectToRect(bitmap, src, dst, paint);
    }
}

void SkBBoxRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& mat,
                                    const SkPaint* paint) {
    SkMatrix m = mat;
    SkRect bbox = {0, 0, SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())};
    m.mapRect(&bbox);
    if (this->transformBounds(bbox, paint)) {
        INHERITED::drawBitmapMatrix(bitmap, mat, paint);
    }
}

void SkBBoxRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
                                  const SkRect& dst, const SkPaint* paint) {
    if (this->transformBounds(dst, paint)) {
        INHERITED::drawBitmapNine(bitmap, center, dst, paint);
    }
}

void SkBBoxRecord::drawPosText(const void* text, size_t byteLength,
                               const SkPoint pos[], const SkPaint& paint) {
    SkRect bbox;
    bbox.set(pos, paint.countText(text, byteLength));
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);
    bbox.fTop += metrics.fTop;
    bbox.fBottom += metrics.fBottom;

    // pad on left and right by half of max vertical glyph extents
    SkScalar pad = (metrics.fTop - metrics.fBottom) / 2;
    bbox.fLeft += pad;
    bbox.fRight -= pad;

    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawPosText(text, byteLength, pos, paint);
    }
}

void SkBBoxRecord::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
                                SkScalar constY, const SkPaint& paint) {
    SkRect bbox;
    size_t numChars = paint.countText(text, byteLength);
    if (numChars > 0) {
        bbox.fLeft  = xpos[0];
        bbox.fRight = xpos[numChars - 1];
        // if we had a guarantee that these will be monotonically increasing, this could be sped up
        for (size_t i = 1; i < numChars; ++i) {
            if (xpos[i] < bbox.fLeft) {
                bbox.fLeft = xpos[i];
            }
            if (xpos[i] > bbox.fRight) {
                bbox.fRight = xpos[i];
            }
        }
        SkPaint::FontMetrics metrics;
        paint.getFontMetrics(&metrics);

        // pad horizontally by max glyph height
        SkScalar pad = (metrics.fTop - metrics.fBottom);
        bbox.fLeft  += pad;
        bbox.fRight -= pad;

        bbox.fTop    = metrics.fTop + constY;
        bbox.fBottom = metrics.fBottom + constY;
        if (!this->transformBounds(bbox, &paint)) {
            return;
        }
    }
    INHERITED::drawPosTextH(text, byteLength, xpos, constY, paint);
}

void SkBBoxRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
                              const SkPaint* paint) {
    SkRect bbox;
    bbox.set(SkIRect::MakeXYWH(left, top, bitmap.width(), bitmap.height()));
    this->handleBBox(bbox); // directly call handleBBox, matrix is ignored
    INHERITED::drawSprite(bitmap, left, top, paint);
}

void SkBBoxRecord::drawTextOnPath(const void* text, size_t byteLength,
                                  const SkPath& path, const SkMatrix* matrix,
                                  const SkPaint& paint) {
    SkRect bbox = path.getBounds();
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);

    // pad out all sides by the max glyph height above baseline
    SkScalar pad = metrics.fTop;
    bbox.fLeft += pad;
    bbox.fRight -= pad;
    bbox.fTop += pad;
    bbox.fBottom -= pad;

    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawTextOnPath(text, byteLength, path, matrix, paint);
    }
}

void SkBBoxRecord::drawVertices(VertexMode mode, int vertexCount,
                                const SkPoint vertices[], const SkPoint texs[],
                                const SkColor colors[], SkXfermode* xfer,
                                const uint16_t indices[], int indexCount,
                                const SkPaint& paint) {
    SkRect bbox;
    bbox.set(vertices, vertexCount);
    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawVertices(mode, vertexCount, vertices, texs,
                                colors, xfer, indices, indexCount, paint);
    }
}

void SkBBoxRecord::drawPicture(SkPicture& picture) {
    if (picture.width() > 0 && picture.height() > 0 &&
        this->transformBounds(SkRect::MakeWH(picture.width(), picture.height()), NULL)) {
        INHERITED::drawPicture(picture);
    }
}

bool SkBBoxRecord::transformBounds(const SkRect& bounds, const SkPaint* paint) {
    SkRect outBounds = bounds;
    outBounds.sort();

    if (paint) {
        // account for stroking, path effects, shadows, etc
        if (paint->canComputeFastBounds()) {
            SkRect temp;
            outBounds = paint->computeFastBounds(outBounds, &temp);
        } else {
            // set bounds to current clip
            if (!this->getClipBounds(&outBounds)) {
                // current clip is empty
                return false;
            }
        }
    }

    if (!this->quickReject(outBounds)) {
        this->getTotalMatrix().mapRect(&outBounds);
        this->handleBBox(outBounds);
        return true;
    }

    return false;
}

<commit_msg>Fix assertion caused by change in 7117.<commit_after>
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkBBoxRecord.h"

void SkBBoxRecord::drawOval(const SkRect& rect, const SkPaint& paint) {
    if (this->transformBounds(rect, &paint)) {
        INHERITED::drawOval(rect, paint);
    }
}

void SkBBoxRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
    if (this->transformBounds(rrect.rect(), &paint)) {
        INHERITED::drawRRect(rrect, paint);
    }
}

void SkBBoxRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
    if (this->transformBounds(rect, &paint)) {
        INHERITED::drawRect(rect, paint);
    }
}

void SkBBoxRecord::drawPath(const SkPath& path, const SkPaint& paint) {
    if (path.isInverseFillType()) {
        // If path is inverse filled, use the current clip bounds as the
        // path's device-space bounding box.
        SkIRect clipBounds;
        if (this->getClipDeviceBounds(&clipBounds)) {
            this->handleBBox(SkRect::MakeFromIRect(clipBounds));
            INHERITED::drawPath(path, paint);
        }
    } else if (this->transformBounds(path.getBounds(), &paint)) {
        INHERITED::drawPath(path, paint);
    }
}

void SkBBoxRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
                              const SkPaint& paint) {
    SkRect bbox;
    bbox.set(pts, count);
    // Small min width value, just to ensure hairline point bounding boxes aren't empty.
    // Even though we know hairline primitives are drawn one pixel wide, we do not use a
    // minimum of 1 because the playback scale factor is unknown at record time. Later
    // outsets will take care of adding additional padding for antialiasing and rounding out
    // to integer device coordinates, guaranteeing that the rasterized pixels will be included
    // in the computed bounds.
    // Note: The device coordinate outset in SkBBoxHierarchyRecord::handleBBox is currently
    // done in the recording coordinate space, which is wrong.
    // http://code.google.com/p/skia/issues/detail?id=1021
    static const SkScalar kMinWidth = SkFloatToScalar(0.01f);
    SkScalar halfStrokeWidth = SkMaxScalar(paint.getStrokeWidth(), kMinWidth) / 2;
    bbox.outset(halfStrokeWidth, halfStrokeWidth);
    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawPoints(mode, count, pts, paint);
    }
}

void SkBBoxRecord::drawPaint(const SkPaint& paint) {
    SkRect bbox;
    if (this->getClipBounds(&bbox)) {
        if (this->transformBounds(bbox, &paint)) {
            INHERITED::drawPaint(paint);
        }
    }
}

void SkBBoxRecord::clear(SkColor color) {
    SkISize size = this->getDeviceSize();
    SkRect bbox = {0, 0, SkIntToScalar(size.width()), SkIntToScalar(size.height())};
    this->handleBBox(bbox);
    INHERITED::clear(color);
}

void SkBBoxRecord::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
                            const SkPaint& paint) {
    SkRect bbox;
    paint.measureText(text, byteLength, &bbox);
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);

    // Vertical and aligned text need to be offset
    if (paint.isVerticalText()) {
        SkScalar h = bbox.fBottom - bbox.fTop;
        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
            bbox.fTop    -= h / 2;
            bbox.fBottom -= h / 2;
        }
        // Pad top and bottom with max extents from FontMetrics
        bbox.fBottom += metrics.fBottom;
        bbox.fTop += metrics.fTop;
    } else {
        SkScalar w = bbox.fRight - bbox.fLeft;
        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
            bbox.fLeft  -= w / 2;
            bbox.fRight -= w / 2;
        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
            bbox.fLeft  -= w;
            bbox.fRight -= w;
        }
        // Set vertical bounds to max extents from font metrics
        bbox.fTop = metrics.fTop;
        bbox.fBottom = metrics.fBottom;
    }

    // Pad horizontal bounds on each side by half of max vertical extents (this is sort of
    // arbitrary, but seems to produce reasonable results, if there were a way of getting max
    // glyph X-extents to pad by, that may be better here, but FontMetrics fXMin and fXMax seem
    // incorrect on most platforms (too small in Linux, never even set in Windows).
    SkScalar pad = (metrics.fBottom - metrics.fTop) / 2;
    bbox.fLeft  -= pad;
    bbox.fRight += pad;

    bbox.fLeft += x;
    bbox.fRight += x;
    bbox.fTop += y;
    bbox.fBottom += y;
    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawText(text, byteLength, x, y, paint);
    }
}

void SkBBoxRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
                              const SkPaint* paint) {
    SkRect bbox = {left, top, left + bitmap.width(), top + bitmap.height()};
    if (this->transformBounds(bbox, paint)) {
        INHERITED::drawBitmap(bitmap, left, top, paint);
    }
}

void SkBBoxRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
                                  const SkRect& dst, const SkPaint* paint) {
    if (this->transformBounds(dst, paint)) {
        INHERITED::drawBitmapRectToRect(bitmap, src, dst, paint);
    }
}

void SkBBoxRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& mat,
                                    const SkPaint* paint) {
    SkMatrix m = mat;
    SkRect bbox = {0, 0, SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())};
    m.mapRect(&bbox);
    if (this->transformBounds(bbox, paint)) {
        INHERITED::drawBitmapMatrix(bitmap, mat, paint);
    }
}

void SkBBoxRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
                                  const SkRect& dst, const SkPaint* paint) {
    if (this->transformBounds(dst, paint)) {
        INHERITED::drawBitmapNine(bitmap, center, dst, paint);
    }
}

void SkBBoxRecord::drawPosText(const void* text, size_t byteLength,
                               const SkPoint pos[], const SkPaint& paint) {
    SkRect bbox;
    bbox.set(pos, paint.countText(text, byteLength));
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);
    bbox.fTop += metrics.fTop;
    bbox.fBottom += metrics.fBottom;

    // pad on left and right by half of max vertical glyph extents
    SkScalar pad = (metrics.fTop - metrics.fBottom) / 2;
    bbox.fLeft += pad;
    bbox.fRight -= pad;

    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawPosText(text, byteLength, pos, paint);
    }
}

void SkBBoxRecord::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
                                SkScalar constY, const SkPaint& paint) {
    SkRect bbox;
    size_t numChars = paint.countText(text, byteLength);
    if (numChars > 0) {
        bbox.fLeft  = xpos[0];
        bbox.fRight = xpos[numChars - 1];
        // if we had a guarantee that these will be monotonically increasing, this could be sped up
        for (size_t i = 1; i < numChars; ++i) {
            if (xpos[i] < bbox.fLeft) {
                bbox.fLeft = xpos[i];
            }
            if (xpos[i] > bbox.fRight) {
                bbox.fRight = xpos[i];
            }
        }
        SkPaint::FontMetrics metrics;
        paint.getFontMetrics(&metrics);

        // pad horizontally by max glyph height
        SkScalar pad = (metrics.fTop - metrics.fBottom);
        bbox.fLeft  += pad;
        bbox.fRight -= pad;

        bbox.fTop    = metrics.fTop + constY;
        bbox.fBottom = metrics.fBottom + constY;
        if (!this->transformBounds(bbox, &paint)) {
            return;
        }
    }
    INHERITED::drawPosTextH(text, byteLength, xpos, constY, paint);
}

void SkBBoxRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
                              const SkPaint* paint) {
    SkRect bbox;
    bbox.set(SkIRect::MakeXYWH(left, top, bitmap.width(), bitmap.height()));
    this->handleBBox(bbox); // directly call handleBBox, matrix is ignored
    INHERITED::drawSprite(bitmap, left, top, paint);
}

void SkBBoxRecord::drawTextOnPath(const void* text, size_t byteLength,
                                  const SkPath& path, const SkMatrix* matrix,
                                  const SkPaint& paint) {
    SkRect bbox = path.getBounds();
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);

    // pad out all sides by the max glyph height above baseline
    SkScalar pad = metrics.fTop;
    bbox.fLeft += pad;
    bbox.fRight -= pad;
    bbox.fTop += pad;
    bbox.fBottom -= pad;

    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawTextOnPath(text, byteLength, path, matrix, paint);
    }
}

void SkBBoxRecord::drawVertices(VertexMode mode, int vertexCount,
                                const SkPoint vertices[], const SkPoint texs[],
                                const SkColor colors[], SkXfermode* xfer,
                                const uint16_t indices[], int indexCount,
                                const SkPaint& paint) {
    SkRect bbox;
    bbox.set(vertices, vertexCount);
    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawVertices(mode, vertexCount, vertices, texs,
                                colors, xfer, indices, indexCount, paint);
    }
}

void SkBBoxRecord::drawPicture(SkPicture& picture) {
    if (picture.width() > 0 && picture.height() > 0 &&
        this->transformBounds(SkRect::MakeWH(picture.width(), picture.height()), NULL)) {
        INHERITED::drawPicture(picture);
    }
}

bool SkBBoxRecord::transformBounds(const SkRect& bounds, const SkPaint* paint) {
    SkRect outBounds = bounds;
    outBounds.sort();

    if (paint) {
        // account for stroking, path effects, shadows, etc
        if (paint->canComputeFastBounds()) {
            SkRect temp;
            outBounds = paint->computeFastBounds(outBounds, &temp);
        } else {
            // set bounds to current clip
            if (!this->getClipBounds(&outBounds)) {
                // current clip is empty
                return false;
            }
        }
    }

    if (!outBounds.isEmpty() && !this->quickReject(outBounds)) {
        this->getTotalMatrix().mapRect(&outBounds);
        this->handleBBox(outBounds);
        return true;
    }

    return false;
}

<|endoftext|>


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

#include "include/core/SkColorFilter.h"
#include "include/core/SkRSXform.h"
#include "src/core/SkBlendModePriv.h"
#include "src/core/SkColorSpacePriv.h"
#include "src/core/SkColorSpaceXformSteps.h"
#include "src/core/SkCoreBlitters.h"
#include "src/core/SkDraw.h"
#include "src/core/SkRasterPipeline.h"
#include "src/core/SkScan.h"
#include "src/shaders/SkShaderBase.h"

#include "include/core/SkMatrix.h"
#include "src/core/SkScan.h"

static void fill_rect(const SkMatrix& ctm, const SkRasterClip& rc,
                      const SkRect& r, SkBlitter* blitter) {
    if (ctm.rectStaysRect()) {
        SkRect dr;
        ctm.mapRect(&dr, r);
        SkScan::FillRect(dr, rc, blitter);
    } else {
        SkPath path;
        path.addRect(r);
        path.transform(ctm);
        SkScan::FillPath(path, rc, blitter);
    }
}

static void load_color(SkRasterPipeline_UniformColorCtx* ctx, const float rgba[]) {
    // only need one of these. can I query the pipeline to know if its lowp or highp?
    ctx->rgba[0] = SkScalarRoundToInt(rgba[0]*255); ctx->r = rgba[0];
    ctx->rgba[1] = SkScalarRoundToInt(rgba[1]*255); ctx->g = rgba[1];
    ctx->rgba[2] = SkScalarRoundToInt(rgba[2]*255); ctx->b = rgba[2];
    ctx->rgba[3] = SkScalarRoundToInt(rgba[3]*255); ctx->a = rgba[3];
}

void SkDraw::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect textures[],
                       const SkColor colors[], int count, SkBlendMode bmode, const SkPaint& paint) {
    sk_sp<SkShader> atlasShader = atlas->makeShader();
    if (!atlasShader) {
        return;
    }

    SkPaint p(paint);
    p.setAntiAlias(false);  // we never respect this for drawAtlas(or drawVertices)
    p.setStyle(SkPaint::kFill_Style);
    p.setShader(nullptr);
    p.setMaskFilter(nullptr);

    SkSTArenaAlloc<256> alloc;
    SkRasterPipeline pipeline(&alloc);
    SkStageRec rec = {
        &pipeline, &alloc, fDst.colorType(), fDst.colorSpace(), p, nullptr, *fMatrix
    };

    SkStageUpdater* updator = as_SB(atlasShader.get())->appendUpdatableStages(rec);
    if (!updator) {
        SkDraw draw(*this);

        p.setShader(atlasShader);
        for (int i = 0; i < count; ++i) {
            if (colors) {
                p.setShader(SkShaders::Blend(bmode, SkShaders::Color(colors[i]), atlasShader));
            }
            SkMatrix mx;
            mx.setRSXform(xform[i]);
            mx.preTranslate(-textures[i].fLeft, -textures[i].fTop);
            mx.postConcat(*fMatrix);
            draw.fMatrix = &mx;
            draw.drawRect(textures[i], p);
        }
        return;
    }

    SkRasterPipeline_UniformColorCtx* uniformCtx = nullptr;
    SkColorSpaceXformSteps steps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
                                 rec.fDstCS,          kUnpremul_SkAlphaType);

    if (colors) {
        // we will late-bind the values in ctx, once for each color in the loop
        uniformCtx = alloc.make<SkRasterPipeline_UniformColorCtx>();
        rec.fPipeline->append(SkRasterPipeline::uniform_color_dst, uniformCtx);
        SkBlendMode_AppendStages(bmode, rec.fPipeline);
    }

    bool isOpaque = !colors && atlasShader->isOpaque();
    if (p.getAlphaf() != 1) {
        rec.fPipeline->append(SkRasterPipeline::scale_1_float, alloc.make<float>(p.getAlphaf()));
        isOpaque = false;
    }

    auto blitter = SkCreateRasterPipelineBlitter(fDst, p, pipeline, isOpaque, &alloc);

    for (int i = 0; i < count; ++i) {
        if (colors) {
            SkColor4f c4 = SkColor4f::FromColor(colors[i]);
            steps.apply(c4.vec());
            load_color(uniformCtx, c4.premul().vec());
        }

        SkMatrix mx;
        mx.setRSXform(xform[i]);
        mx.preTranslate(-textures[i].fLeft, -textures[i].fTop);
        mx.postConcat(*fMatrix);

        updator->update(mx, nullptr);
        fill_rect(mx, *fRC, textures[i], blitter);
    }
}
<commit_msg>use scratch path to save on mallocs in drawAtlas<commit_after>/*
 * Copyright 2019 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkColorFilter.h"
#include "include/core/SkRSXform.h"
#include "src/core/SkBlendModePriv.h"
#include "src/core/SkColorSpacePriv.h"
#include "src/core/SkColorSpaceXformSteps.h"
#include "src/core/SkCoreBlitters.h"
#include "src/core/SkDraw.h"
#include "src/core/SkRasterPipeline.h"
#include "src/core/SkScan.h"
#include "src/shaders/SkShaderBase.h"

#include "include/core/SkMatrix.h"
#include "src/core/SkScan.h"

static void fill_rect(const SkMatrix& ctm, const SkRasterClip& rc,
                      const SkRect& r, SkBlitter* blitter, SkPath* scratchPath) {
    if (ctm.rectStaysRect()) {
        SkRect dr;
        ctm.mapRect(&dr, r);
        SkScan::FillRect(dr, rc, blitter);
    } else {
        scratchPath->rewind();
        scratchPath->addRect(r);
        scratchPath->transform(ctm);
        SkScan::FillPath(*scratchPath, rc, blitter);
    }
}

static void load_color(SkRasterPipeline_UniformColorCtx* ctx, const float rgba[]) {
    // only need one of these. can I query the pipeline to know if its lowp or highp?
    ctx->rgba[0] = SkScalarRoundToInt(rgba[0]*255); ctx->r = rgba[0];
    ctx->rgba[1] = SkScalarRoundToInt(rgba[1]*255); ctx->g = rgba[1];
    ctx->rgba[2] = SkScalarRoundToInt(rgba[2]*255); ctx->b = rgba[2];
    ctx->rgba[3] = SkScalarRoundToInt(rgba[3]*255); ctx->a = rgba[3];
}

void SkDraw::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect textures[],
                       const SkColor colors[], int count, SkBlendMode bmode, const SkPaint& paint) {
    sk_sp<SkShader> atlasShader = atlas->makeShader();
    if (!atlasShader) {
        return;
    }

    SkPaint p(paint);
    p.setAntiAlias(false);  // we never respect this for drawAtlas(or drawVertices)
    p.setStyle(SkPaint::kFill_Style);
    p.setShader(nullptr);
    p.setMaskFilter(nullptr);

    SkSTArenaAlloc<256> alloc;
    SkRasterPipeline pipeline(&alloc);
    SkStageRec rec = {
        &pipeline, &alloc, fDst.colorType(), fDst.colorSpace(), p, nullptr, *fMatrix
    };

    SkStageUpdater* updator = as_SB(atlasShader.get())->appendUpdatableStages(rec);
    if (!updator) {
        SkDraw draw(*this);

        p.setShader(atlasShader);
        for (int i = 0; i < count; ++i) {
            if (colors) {
                p.setShader(SkShaders::Blend(bmode, SkShaders::Color(colors[i]), atlasShader));
            }
            SkMatrix mx;
            mx.setRSXform(xform[i]);
            mx.preTranslate(-textures[i].fLeft, -textures[i].fTop);
            mx.postConcat(*fMatrix);
            draw.fMatrix = &mx;
            draw.drawRect(textures[i], p);
        }
        return;
    }

    SkRasterPipeline_UniformColorCtx* uniformCtx = nullptr;
    SkColorSpaceXformSteps steps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
                                 rec.fDstCS,          kUnpremul_SkAlphaType);

    if (colors) {
        // we will late-bind the values in ctx, once for each color in the loop
        uniformCtx = alloc.make<SkRasterPipeline_UniformColorCtx>();
        rec.fPipeline->append(SkRasterPipeline::uniform_color_dst, uniformCtx);
        SkBlendMode_AppendStages(bmode, rec.fPipeline);
    }

    bool isOpaque = !colors && atlasShader->isOpaque();
    if (p.getAlphaf() != 1) {
        rec.fPipeline->append(SkRasterPipeline::scale_1_float, alloc.make<float>(p.getAlphaf()));
        isOpaque = false;
    }

    auto blitter = SkCreateRasterPipelineBlitter(fDst, p, pipeline, isOpaque, &alloc);
    SkPath scratchPath;

    for (int i = 0; i < count; ++i) {
        if (colors) {
            SkColor4f c4 = SkColor4f::FromColor(colors[i]);
            steps.apply(c4.vec());
            load_color(uniformCtx, c4.premul().vec());
        }

        SkMatrix mx;
        mx.setRSXform(xform[i]);
        mx.preTranslate(-textures[i].fLeft, -textures[i].fTop);
        mx.postConcat(*fMatrix);

        updator->update(mx, nullptr);
        fill_rect(mx, *fRC, textures[i], blitter, &scratchPath);
    }
}
<|endoftext|>


<commit_before>/// \file
/// \ingroup tutorial_graphs
/// \notebook
/// Draw a graph with text attached to each point.
/// The text is drawn in a TExec function attached to the TGraph,
/// therefore if the text is
/// moved interactively, it will be automatically updated.
///
/// \macro_image
/// \macro_code
///
/// \author Olivier Couet

void graphtext() {
   TCanvas *c = new TCanvas("c","A Simple Graph Example with Text",700,500);
   c->SetGrid();

   const Int_t n = 10;
   TGraph *gr = new TGraph(n);
   gr->SetTitle("A Simple Graph Example with Text");
   gr->SetMarkerStyle(20);
   TExec *ex = new TExec("ex","drawtext();");
   gr->GetListOfFunctions()->Add(ex);

   Double_t x, y;
   for (Int_t i=0;i<n;i++) {
      x = i*0.1;
      y = 10*sin(x+0.2);
      gr->SetPoint(i,x,y);

   }
   gr->Draw("ALP");
}

void drawtext()
{
   Int_t i,n;
   Double_t x,y;
   TLatex l;

   l.SetTextSize(0.025);
   l.SetTextFont(42);
   l.SetTextAlign(21);
   l.SetTextColor(kBlue);

   TGraph *g = (TGraph*)gPad->GetListOfPrimitives()->FindObject("Graph");
   n = g->GetN();

   for (i=0; i<n; i++) {
      g->GetPoint(i,x,y);
      l.PaintText(x,y+0.2,Form("(%4.2f,%4.2f)",x,y));
   }
}

<commit_msg>Re-arrange the doc.<commit_after>/// \file
/// \ingroup tutorial_graphs
/// \notebook
/// Draw a graph with text attached to each point.
/// The text is drawn in a TExec function attached to the TGraph,
/// therefore if the a graph's point is
/// moved interactively, the text will be automatically updated.
///
/// \macro_image
/// \macro_code
///
/// \author Olivier Couet

void graphtext() {
   TCanvas *c = new TCanvas("c","A Simple Graph Example with Text",700,500);
   c->SetGrid();

   const Int_t n = 10;
   auto *gr = new TGraph(n);
   gr->SetTitle("A Simple Graph Example with Text");
   gr->SetMarkerStyle(20);
   auto ex = new TExec("ex","drawtext();");
   gr->GetListOfFunctions()->Add(ex);

   Double_t x, y;
   for (Int_t i=0;i<n;i++) {
      x = i*0.1;
      y = 10*sin(x+0.2);
      gr->SetPoint(i,x,y);

   }
   gr->Draw("ALP");
}

void drawtext()
{
   Int_t i,n;
   Double_t x,y;
   TLatex l;

   l.SetTextSize(0.025);
   l.SetTextFont(42);
   l.SetTextAlign(21);
   l.SetTextColor(kBlue);

   auto g = (TGraph*)gPad->GetListOfPrimitives()->FindObject("Graph");
   n = g->GetN();

   for (i=0; i<n; i++) {
      g->GetPoint(i,x,y);
      l.PaintText(x,y+0.2,Form("(%4.2f,%4.2f)",x,y));
   }
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: global.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 05:03:57 $
 *
 *  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 _OSL_PROCESS_H_
#include <osl/process.h>
#endif
#ifndef _RTL_OSTRINGBUFFER_HXX_
#include <rtl/strbuf.hxx>
#endif
#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

#ifndef     _OSL_THREAD_H_
#include    <osl/thread.h>
#endif
#ifndef     _OSL_FILE_HXX_
#include    <osl/file.hxx>
#endif

#include <stdlib.h>
#include <stdio.h>
#if defined(SAL_W32) || defined(SAL_OS2)
#include <io.h>
#include <direct.h>
#include <errno.h>
#endif

#ifdef UNX
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#endif

#ifndef _CODEMAKER_GLOBAL_HXX_
#include    <codemaker/global.hxx>
#endif

#ifdef SAL_UNX
#define SEPARATOR '/'
#else
#define SEPARATOR '\\'
#endif

using namespace ::rtl;
using namespace ::osl;

OString makeTempName(sal_Char* prefix)
{
    static OUString uTMP( RTL_CONSTASCII_USTRINGPARAM("TMP") );
    static OUString uTEMP( RTL_CONSTASCII_USTRINGPARAM("TEMP") );
    OUString        uPrefix( RTL_CONSTASCII_USTRINGPARAM("cmk_") );
    OUString        uPattern;

    sal_Char*   pPrefix = "cmk_";
    sal_Char    tmpPattern[512];
    sal_Char    *pTmpName = NULL;

    if (prefix)
        pPrefix = prefix;

    if ( osl_getEnvironment(uTMP.pData, &uPattern.pData) != osl_Process_E_None )
    {
        if ( osl_getEnvironment(uTEMP.pData, &uPattern.pData) != osl_Process_E_None )
        {
#if defined(SAL_W32) || defined(SAL_OS2)
            OSL_ASSERT( sizeof(tmpPattern) > RTL_CONSTASCII_LENGTH( "." ) );
            strncpy(tmpPattern, ".", sizeof(tmpPattern)-1);
#else
            OSL_ASSERT( sizeof(tmpPattern) > RTL_CONSTASCII_LENGTH( "/tmp" ) );
            strncpy(tmpPattern, "/tmp", sizeof(tmpPattern)-1);
#endif
        }
    }

    if (uPattern.getLength())
    {
        OString aOStr( OUStringToOString(uPattern, RTL_TEXTENCODING_UTF8) );
        OSL_ASSERT( sizeof(tmpPattern) > aOStr.getLength() );
        strncpy(tmpPattern, aOStr.getStr(), sizeof(tmpPattern)-1);
    }

#ifdef SAL_W32
    OSL_ASSERT( sizeof(tmpPattern) > ( strlen(tmpPattern)
                                       + RTL_CONSTASCII_LENGTH("\\")
                                       + strlen(pPrefix)
                                       + RTL_CONSTASCII_LENGTH("XXXXXX") ) );
    strncat(tmpPattern, "\\", sizeof(tmpPattern)-1-strlen(tmpPattern));
    strncat(tmpPattern, pPrefix, sizeof(tmpPattern)-1-strlen(tmpPattern));
    strncat(tmpPattern, "XXXXXX", sizeof(tmpPattern)-1-strlen(tmpPattern));
    pTmpName = mktemp(tmpPattern);
#endif

#ifdef SAL_OS2
    char* tmpname = tempnam(NULL, prefix);
    OSL_ASSERT( sizeof(tmpPattern) > strlen(tmpname) );
    strncpy(tmpPattern, tmpname, sizeof(tmpPattern)-1);
    pTmpName = tmpPattern;
#endif

#ifdef SAL_UNX
    OSL_ASSERT( sizeof(tmpPattern) > ( strlen(tmpPattern)
                                       + RTL_CONSTASCII_LENGTH("/")
                                       + strlen(pPrefix)
                                       + RTL_CONSTASCII_LENGTH("XXXXXX") ) );
    strncat(tmpPattern, "/", sizeof(tmpPattern)-1-strlen(tmpPattern));
    strncat(tmpPattern, pPrefix, sizeof(tmpPattern)-1-strlen(tmpPattern));
    strncat(tmpPattern, "XXXXXX", sizeof(tmpPattern)-1-strlen(tmpPattern));
    pTmpName = mktemp(tmpPattern);
#endif

    return OString(pTmpName);
}

OString createFileNameFromType( const OString& destination,
                                const OString typeName,
                                const OString postfix,
                                sal_Bool bLowerCase,
                                const OString prefix )
{
    OString type(typeName);

    if (bLowerCase)
    {
        type = typeName.toAsciiLowerCase();
    }

    sal_uInt32 length = destination.getLength();

    sal_Bool withPoint = sal_False;
    if (length == 0)
    {
        length++;
        withPoint = sal_True;
    }

    length += prefix.getLength() + type.getLength() + postfix.getLength();

    sal_Bool withSeperator = sal_False;
    if (destination.getStr()[destination.getLength()] != '\\' &&
        destination.getStr()[destination.getLength()] != '/' &&
        type.getStr()[0] != '\\' &&
        type.getStr()[0] != '/')
    {
        length++;
        withSeperator = sal_True;
    }

    OStringBuffer nameBuffer(length);

    if (withPoint)
        nameBuffer.append('.');
    else
        nameBuffer.append(destination.getStr(), destination.getLength());

    if (withSeperator)
        nameBuffer.append("/", 1);

    OString tmpStr(type);
    if (prefix.getLength() > 0)
    {
        tmpStr = type.replaceAt(type.lastIndexOf('/')+1, 0, prefix);
    }

    nameBuffer.append(tmpStr.getStr(), tmpStr.getLength());
    nameBuffer.append(postfix.getStr(), postfix.getLength());

    OString fileName(nameBuffer);

    sal_Char token;
#ifdef SAL_UNX
    fileName = fileName.replace('\\', '/');
    token = '/';
#else
    fileName = fileName.replace('/', '\\');
    token = '\\';
#endif

    nameBuffer = OStringBuffer(length);

    sal_Int32 nIndex = 0;
    do
    {
        nameBuffer.append(fileName.getToken( 0, token, nIndex ).getStr());

        if (nameBuffer.getLength() == 0 || OString(".") == nameBuffer.getStr())
        {
            nameBuffer.append(token);
            continue;
        }

#ifdef SAL_UNX
        if (mkdir((char*)nameBuffer.getStr(), 0777) == -1)
#else
           if (mkdir((char*)nameBuffer.getStr()) == -1)
#endif
        {
            if ( errno == ENOENT )
                return OString();
        }

        nameBuffer.append(token);
    }
    while ( nIndex >= 0 );

    return fileName;
}

sal_Bool fileExists(const OString& fileName)
{
    FILE  *f= fopen(fileName.getStr(), "r");

    if (f != NULL)
    {
        fclose(f);
        return sal_True;
    }

    return sal_False;
}

sal_Bool checkFileContent(const OString& targetFileName, const OString& tmpFileName)
{
    FILE  *target = fopen(targetFileName.getStr(), "r");
    FILE  *tmp = fopen(tmpFileName.getStr(), "r");
    sal_Bool ret = sal_False;

    if (target != NULL && tmp != NULL)
    {
        sal_Bool    bFindChanges = sal_False;
        sal_Char    buffer1[1024+1];
        sal_Char    buffer2[1024+1];
        sal_Int32   n1 = 0;
        sal_Int32   n2 = 0;

        while ( !bFindChanges && !feof(target) && !feof(tmp))
        {
            n1 = fread(buffer1, sizeof(sal_Char), 1024, target);
            n2 = fread(buffer2, sizeof(sal_Char), 1024, tmp);

            if ( n1 != n2 )
            {
                bFindChanges = sal_True;
            }
            else
            {
                if ( rtl_compareMemory(buffer1, buffer2, n2) != 0 )
                    bFindChanges =  sal_True;
            }
        }

        fclose(target);
        fclose(tmp);

        if ( bFindChanges )
        {
            if ( !unlink(targetFileName.getStr()) )
                if ( !rename(tmpFileName.getStr(), targetFileName.getStr()) )
                    ret = sal_True;
        }
        else
        {
            if ( !unlink(tmpFileName.getStr()) )
                ret = sal_True;
        }
    }

    return ret;
}

const OString inGlobalSet(const OUString & rValue)
{
    OString sValue( OUStringToOString(rValue, RTL_TEXTENCODING_UTF8) );
    static StringSet aGlobalMap;
    StringSet::iterator iter = aGlobalMap.find( sValue );
    if( iter != aGlobalMap.end() )
        return *iter;
    return *(aGlobalMap.insert( sValue ).first);
}

static sal_Bool isFileUrl(const OString& fileName)
{
    if (fileName.indexOf("file://") == 0 )
        return sal_True;
    return sal_False;
}

OUString convertToFileUrl(const OString& fileName)
{
    if ( isFileUrl(fileName) )
    {
        return OStringToOUString(fileName, osl_getThreadTextEncoding());
    }

    OUString uUrlFileName;
    OUString uFileName(fileName.getStr(), fileName.getLength(), osl_getThreadTextEncoding());
    if ( fileName.indexOf('.') == 0 || fileName.indexOf(SEPARATOR) < 0 )
    {
        OUString uWorkingDir;
        OSL_VERIFY( osl_getProcessWorkingDir(&uWorkingDir.pData) == osl_Process_E_None );
        OSL_VERIFY( FileBase::getAbsoluteFileURL(uWorkingDir, uFileName, uUrlFileName) == FileBase::E_None );
    } else
    {
        OSL_VERIFY( FileBase::getFileURLFromSystemPath(uFileName, uUrlFileName) == FileBase::E_None );
    }

    return uUrlFileName;
}

//*************************************************************************
// FileStream
//*************************************************************************
FileStream::FileStream()
{
}

FileStream::FileStream(const OString& name, FileAccessMode mode)
    : m_pFile(NULL)
{
    if ( name.getLength() > 0 )
    {
        m_name = name;
        m_pFile = fopen(m_name, checkAccessMode(mode));
    }
}

FileStream::~FileStream()
{
    if ( isValid() )
    {
        fflush(m_pFile);
        fclose(m_pFile);
    }
}

sal_Bool FileStream::isValid()
{
    if ( m_pFile )
        return sal_True;

    return sal_False;
}

void FileStream::open(const OString& name, FileAccessMode mode)
{
    if ( name.getLength() > 0 )
    {
        m_name = name;
        m_pFile = fopen(m_name, checkAccessMode(mode));
    }
}

void FileStream::close()
{
    if ( isValid() )
    {
        fflush(m_pFile);
        fclose(m_pFile);
        m_pFile = NULL;
        m_name = OString();
    }
}

sal_Int32 FileStream::getSize()
{
    sal_Int32 pos = 0;
    sal_Int32 size = 0;
    if ( isValid() )
    {
        fflush(m_pFile);
        pos = ftell(m_pFile);
        if (!fseek(m_pFile, 0, SEEK_END))
            size = ftell(m_pFile);
        fseek(m_pFile, pos, SEEK_SET);
    }
    return size;
}

const sal_Char* FileStream::checkAccessMode(FileAccessMode mode)
{
    switch( mode )
    {
    case FAM_READ:
        return "r";
    case FAM_WRITE:
        return "w";
    case FAM_APPEND:
        return "a";
    case FAM_READWRITE_EXIST:
        return "r+";
    case FAM_READWRITE:
        return "w+";
    case FAM_READAPPEND:
        return "a+";
    }
    return "w+";
}

<commit_msg>INTEGRATION: CWS jscpp1 (1.9.74); FILE MERGED 2005/08/10 07:39:41 jsc 1.9.74.1: #i41875# integrate patch, use osl::FileBase::createTempFile<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: global.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: rt $ $Date: 2005-10-17 13:30:39 $
 *
 *  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 _OSL_PROCESS_H_
#include <osl/process.h>
#endif
#ifndef _RTL_OSTRINGBUFFER_HXX_
#include <rtl/strbuf.hxx>
#endif
#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

#ifndef     _OSL_THREAD_H_
#include    <osl/thread.h>
#endif
#ifndef     _OSL_FILE_HXX_
#include    <osl/file.hxx>
#endif

#include <stdlib.h>
#include <stdio.h>
#if defined(SAL_W32) || defined(SAL_OS2)
#include <io.h>
#include <direct.h>
#include <errno.h>
#endif

#ifdef UNX
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#endif

#ifndef _CODEMAKER_GLOBAL_HXX_
#include    <codemaker/global.hxx>
#endif

#ifdef SAL_UNX
#define SEPARATOR '/'
#else
#define SEPARATOR '\\'
#endif

using namespace ::rtl;
using namespace ::osl;

OString createFileNameFromType( const OString& destination,
                                const OString typeName,
                                const OString postfix,
                                sal_Bool bLowerCase,
                                const OString prefix )
{
    OString type(typeName);

    if (bLowerCase)
    {
        type = typeName.toAsciiLowerCase();
    }

    sal_uInt32 length = destination.getLength();

    sal_Bool withPoint = sal_False;
    if (length == 0)
    {
        length++;
        withPoint = sal_True;
    }

    length += prefix.getLength() + type.getLength() + postfix.getLength();

    sal_Bool withSeperator = sal_False;
    if (destination.getStr()[destination.getLength()] != '\\' &&
        destination.getStr()[destination.getLength()] != '/' &&
        type.getStr()[0] != '\\' &&
        type.getStr()[0] != '/')
    {
        length++;
        withSeperator = sal_True;
    }

    OStringBuffer nameBuffer(length);

    if (withPoint)
        nameBuffer.append('.');
    else
        nameBuffer.append(destination.getStr(), destination.getLength());

    if (withSeperator)
        nameBuffer.append("/", 1);

    OString tmpStr(type);
    if (prefix.getLength() > 0)
    {
        tmpStr = type.replaceAt(type.lastIndexOf('/')+1, 0, prefix);
    }

    nameBuffer.append(tmpStr.getStr(), tmpStr.getLength());
    nameBuffer.append(postfix.getStr(), postfix.getLength());

    OString fileName(nameBuffer);

    sal_Char token;
#ifdef SAL_UNX
    fileName = fileName.replace('\\', '/');
    token = '/';
#else
    fileName = fileName.replace('/', '\\');
    token = '\\';
#endif

    nameBuffer = OStringBuffer(length);

    sal_Int32 nIndex = 0;
    do
    {
        nameBuffer.append(fileName.getToken( 0, token, nIndex ).getStr());

        if (nameBuffer.getLength() == 0 || OString(".") == nameBuffer.getStr())
        {
            nameBuffer.append(token);
            continue;
        }

#ifdef SAL_UNX
        if (mkdir((char*)nameBuffer.getStr(), 0777) == -1)
#else
           if (mkdir((char*)nameBuffer.getStr()) == -1)
#endif
        {
            if ( errno == ENOENT )
                return OString();
        }

        nameBuffer.append(token);
    }
    while ( nIndex >= 0 );

    return fileName;
}

sal_Bool fileExists(const OString& fileName)
{
    FILE  *f= fopen(fileName.getStr(), "r");

    if (f != NULL)
    {
        fclose(f);
        return sal_True;
    }

    return sal_False;
}

sal_Bool checkFileContent(const OString& targetFileName, const OString& tmpFileName)
{
    FILE  *target = fopen(targetFileName.getStr(), "r");
    FILE  *tmp = fopen(tmpFileName.getStr(), "r");
    sal_Bool ret = sal_False;

    if (target != NULL && tmp != NULL)
    {
        sal_Bool    bFindChanges = sal_False;
        sal_Char    buffer1[1024+1];
        sal_Char    buffer2[1024+1];
        sal_Int32   n1 = 0;
        sal_Int32   n2 = 0;

        while ( !bFindChanges && !feof(target) && !feof(tmp))
        {
            n1 = fread(buffer1, sizeof(sal_Char), 1024, target);
            n2 = fread(buffer2, sizeof(sal_Char), 1024, tmp);

            if ( n1 != n2 )
            {
                bFindChanges = sal_True;
            }
            else
            {
                if ( rtl_compareMemory(buffer1, buffer2, n2) != 0 )
                    bFindChanges =  sal_True;
            }
        }

        fclose(target);
        fclose(tmp);

        if ( bFindChanges )
        {
            if ( !unlink(targetFileName.getStr()) )
                if ( !rename(tmpFileName.getStr(), targetFileName.getStr()) )
                    ret = sal_True;
        }
        else
        {
            if ( !unlink(tmpFileName.getStr()) )
                ret = sal_True;
        }
    }

    return ret;
}

const OString inGlobalSet(const OUString & rValue)
{
    OString sValue( OUStringToOString(rValue, RTL_TEXTENCODING_UTF8) );
    static StringSet aGlobalMap;
    StringSet::iterator iter = aGlobalMap.find( sValue );
    if( iter != aGlobalMap.end() )
        return *iter;
    return *(aGlobalMap.insert( sValue ).first);
}

static sal_Bool isFileUrl(const OString& fileName)
{
    if (fileName.indexOf("file://") == 0 )
        return sal_True;
    return sal_False;
}

OUString convertToFileUrl(const OString& fileName)
{
    if ( isFileUrl(fileName) )
    {
        return OStringToOUString(fileName, osl_getThreadTextEncoding());
    }

    OUString uUrlFileName;
    OUString uFileName(fileName.getStr(), fileName.getLength(), osl_getThreadTextEncoding());
    if ( fileName.indexOf('.') == 0 || fileName.indexOf(SEPARATOR) < 0 )
    {
        OUString uWorkingDir;
        OSL_VERIFY( osl_getProcessWorkingDir(&uWorkingDir.pData) == osl_Process_E_None );
        OSL_VERIFY( FileBase::getAbsoluteFileURL(uWorkingDir, uFileName, uUrlFileName) == FileBase::E_None );
    } else
    {
        OSL_VERIFY( FileBase::getFileURLFromSystemPath(uFileName, uUrlFileName) == FileBase::E_None );
    }

    return uUrlFileName;
}

//*************************************************************************
// FileStream
//*************************************************************************
FileStream::FileStream()
{
}

FileStream::FileStream(const OString& name, FileAccessMode mode)
    : m_pFile(NULL)
{
    if ( name.getLength() > 0 )
    {
        m_name = name;
        m_pFile = fopen(m_name, checkAccessMode(mode));
    }
}

FileStream::~FileStream()
{
    if ( isValid() )
    {
        fflush(m_pFile);
        fclose(m_pFile);
    }
}

sal_Bool FileStream::isValid()
{
    if ( m_pFile )
        return sal_True;

    return sal_False;
}

void FileStream::open(const OString& name, FileAccessMode mode)
{
    if ( name.getLength() > 0 )
    {
        m_name = name;
        m_pFile = fopen(m_name, checkAccessMode(mode));
    }
}

void FileStream::close()
{
    if ( isValid() )
    {
        fflush(m_pFile);
        fclose(m_pFile);
        m_pFile = NULL;
        m_name = OString();
    }
}

sal_Int32 FileStream::getSize()
{
    sal_Int32 pos = 0;
    sal_Int32 size = 0;
    if ( isValid() )
    {
        fflush(m_pFile);
        pos = ftell(m_pFile);
        if (!fseek(m_pFile, 0, SEEK_END))
            size = ftell(m_pFile);
        fseek(m_pFile, pos, SEEK_SET);
    }
    return size;
}

const sal_Char* FileStream::checkAccessMode(FileAccessMode mode)
{
    switch( mode )
    {
    case FAM_READ:
        return "r";
    case FAM_WRITE:
        return "w";
    case FAM_APPEND:
        return "a";
    case FAM_READWRITE_EXIST:
        return "r+";
    case FAM_READWRITE:
        return "w+";
    case FAM_READAPPEND:
        return "a+";
    }
    return "w+";
}

<|endoftext|>


<commit_before><commit_msg>ENH: Added remove cache-directory in outdated dataset dialog.<commit_after><|endoftext|>


<commit_before><commit_msg>ColorCubeGenerator: replace deprecated functions.<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: scopeguard.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 17:14:02 $
 *
 *  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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_comphelper.hxx"

#include "comphelper/scopeguard.hxx"
#include "osl/diagnose.h"
#include "com/sun/star/uno/Exception.hpp"

namespace comphelper {

ScopeGuard::~ScopeGuard()
{
    if (m_func)
    {
        if (m_excHandling == IGNORE_EXCEPTIONS)
        {
            try {
                m_func();
            }
            catch (com::sun::star::uno::Exception & exc) {
                (void) exc; // avoid warning about unused variable
                OSL_ENSURE(
                    false, rtl::OUStringToOString(
                        rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                                           "UNO exception occured: ") ) +
                        exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
            }
            catch (...) {
                OSL_ENSURE( false, "unknown exception occured!" );
            }
        }
        else
        {
            m_func();
        }
    }
}

void ScopeGuard::dismiss()
{
    m_func.clear();
}

} // namespace comphelper

<commit_msg>INTEGRATION: CWS changefileheader (1.6.160); FILE MERGED 2008/03/31 12:19:33 rt 1.6.160.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: scopeguard.cxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_comphelper.hxx"

#include "comphelper/scopeguard.hxx"
#include "osl/diagnose.h"
#include "com/sun/star/uno/Exception.hpp"

namespace comphelper {

ScopeGuard::~ScopeGuard()
{
    if (m_func)
    {
        if (m_excHandling == IGNORE_EXCEPTIONS)
        {
            try {
                m_func();
            }
            catch (com::sun::star::uno::Exception & exc) {
                (void) exc; // avoid warning about unused variable
                OSL_ENSURE(
                    false, rtl::OUStringToOString(
                        rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                                           "UNO exception occured: ") ) +
                        exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
            }
            catch (...) {
                OSL_ENSURE( false, "unknown exception occured!" );
            }
        }
        else
        {
            m_func();
        }
    }
}

void ScopeGuard::dismiss()
{
    m_func.clear();
}

} // namespace comphelper

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: scopeguard.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 22:49:31 $
 *
 *  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
 *
 ************************************************************************/

#include "comphelper/scopeguard.hxx"
#include "osl/diagnose.h"
#include "com/sun/star/uno/Exception.hpp"

namespace comphelper {

ScopeGuard::~ScopeGuard()
{
    if (m_func)
    {
        if (m_excHandling == IGNORE_EXCEPTIONS)
        {
            try {
                m_func();
            }
            catch (com::sun::star::uno::Exception & exc) {
                (void) exc; // avoid warning about unused variable
                OSL_ENSURE(
                    false, rtl::OUStringToOString(
                        rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                                           "UNO exception occured: ") ) +
                        exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
            }
            catch (...) {
                OSL_ENSURE( false, "unknown exception occured!" );
            }
        }
        else
        {
            m_func();
        }
    }
}

void ScopeGuard::dismiss()
{
    m_func.clear();
}

} // namespace comphelper

<commit_msg>INTEGRATION: CWS pchfix02 (1.5.36); FILE MERGED 2006/09/01 17:19:44 kaib 1.5.36.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: scopeguard.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 17:14:02 $
 *
 *  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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_comphelper.hxx"

#include "comphelper/scopeguard.hxx"
#include "osl/diagnose.h"
#include "com/sun/star/uno/Exception.hpp"

namespace comphelper {

ScopeGuard::~ScopeGuard()
{
    if (m_func)
    {
        if (m_excHandling == IGNORE_EXCEPTIONS)
        {
            try {
                m_func();
            }
            catch (com::sun::star::uno::Exception & exc) {
                (void) exc; // avoid warning about unused variable
                OSL_ENSURE(
                    false, rtl::OUStringToOString(
                        rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                                           "UNO exception occured: ") ) +
                        exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
            }
            catch (...) {
                OSL_ENSURE( false, "unknown exception occured!" );
            }
        }
        else
        {
            m_func();
        }
    }
}

void ScopeGuard::dismiss()
{
    m_func.clear();
}

} // namespace comphelper

<|endoftext|>


<commit_before>#include "CPU.h"

short CPU::opcode0x07() {
	byte significantBit = AF.hi & 0x80;
	AF.hi <<= 1;

	if (checkFlag(Flag::CARRY_FLAG)) {
		setBit(&AF.hi, 0);
	}
	else {
		clearBit(&AF.hi, 0);
	}

	clearFlags();
	if (significantBit != 0) {
		raiseFlag(Flag::CARRY_FLAG);
	}

    return 4;
}

short CPU::opcode0x0F() {
	byte bitZero = AF.hi & 0x01;
	AF.hi >>= 1;

	clearFlags();
	if (bitZero == 0x01) {
		raiseFlag(Flag::CARRY_FLAG);
	}
	if (AF.hi == 0x00) {
		raiseFlag(Flag::ZERO_FLAG);
	}

    return 4;
}

short CPU::opcode0x17() {
	byte lastBit = AF.hi & 0x80;
	AF.hi <<= 1;

	if (checkFlag(Flag::CARRY_FLAG)) {
		setBit(&AF.hi, 0);
	} else {
		clearBit(&AF.hi, 0);
	}

	clearFlags();
	if (lastBit == 0x01) {
		raiseFlag(Flag::CARRY_FLAG);
	}
	if (AF.hi == 0) {
		raiseFlag(ZERO_FLAG);
	}
    return 4;
}// RLA

short CPU::opcode0x1F() {
	byte firstBit = AF.hi & 0x01;
	AF.hi >>= 1;

	if (checkFlag(Flag::CARRY_FLAG)) {
		setBit(&AF.hi, 7);
	} else {
		clearBit(&AF.hi, 7);
	}

	clearFlags();
	if (firstBit == 0x01) {
		raiseFlag(Flag::CARRY_FLAG);
	}
	return 4;
}// RR A

void CPU::rlc8bitRegister(byte * reg) {
	byte bit= *reg & 0x80;
	*reg <<= 1;

	clearFlags();
	if (bit == 0x01) {
		raiseFlag(Flag::CARRY_FLAG);
	}
	if (*reg == 0x00) {
		raiseFlag(ZERO_FLAG);
	}
}

short CPU::extendedOpcode0x00() {
    rlc8bitRegister(&BC.hi);
    return 8;
}// RLC B

short CPU::extendedOpcode0x01() {
    rlc8bitRegister(&BC.low);
    return 8;
}// RLC C

short CPU::extendedOpcode0x02() {
    rlc8bitRegister(&DE.hi);
    return 8;
}// RLC D

short CPU::extendedOpcode0x03() {
    rlc8bitRegister(&DE.low);
    return 8;
}// RLC E

short CPU::extendedOpcode0x04() {
    rlc8bitRegister(&HL.hi);
    return 8;
}// RLC H

short CPU::extendedOpcode0x05() {
    rlc8bitRegister(&HL.low);
    return 8;
}// RLC L

short CPU::extendedOpcode0x06() {
	byte reg = memory->read(HL.value) ;
	rlc8bitRegister(&reg);
	memory->write(HL.value, reg);

	return 16;
}// RLC (HL)

short CPU::extendedOpcode0x07() {
	byte significantBit = AF.hi & 0x80;
	AF.hi <<= 1;

	if (checkFlag(Flag::CARRY_FLAG)) {
		setBit(&AF.hi, 0);
	} else {
		clearBit(&AF.hi, 0);
	}

	clearFlags();
	if (significantBit != 0) {
		raiseFlag(Flag::CARRY_FLAG);
	}

	if (AF.hi == 0x00) {
		raiseFlag(Flag::ZERO_FLAG);
	}

    return 8;
}// RLC A

void CPU::rrc8bitRegister(byte *reg) {
	byte zeroBit = *reg & 0x01;
	*reg = *reg >> 1;

	clearFlags();
	if (zeroBit == 0x01) {
		raiseFlag(CARRY_FLAG);
	}
	if (*reg == 0) {
		raiseFlag(ZERO_FLAG);
    }
}

short CPU::extendedOpcode0x08() {
    rrc8bitRegister(&BC.hi);
    return 8;
}// RRC B

short CPU::extendedOpcode0x09() {
    rrc8bitRegister(&BC.low);
    return 8;
}// RRC C

short CPU::extendedOpcode0x0A() {
    rrc8bitRegister(&DE.hi);
    return 8;
}// RRC D

short CPU::extendedOpcode0x0B() {
    rrc8bitRegister(&DE.low);
    return 8;
}// RRC E

short CPU::extendedOpcode0x0C() {
    rrc8bitRegister(&HL.hi);
    return 8;
}// RRC H

short CPU::extendedOpcode0x0D() {
    rrc8bitRegister(&HL.low);
    return 8;
}// RRC L

short CPU::extendedOpcode0x0E() {
	byte reg = memory->read(HL.value) ;
	rrc8bitRegister(&reg);
	memory->write(HL.value, reg);
    return 16;
}// RRC (HL)

short CPU::extendedOpcode0x0F() {
	byte bit = AF.hi & 0x01;
	AF.hi >>= 1;

	clearFlags();
	if (bit == 0x01) {
		raiseFlag(Flag::CARRY_FLAG);
	}

	if (AF.hi == 0x00) {
		raiseFlag(Flag::ZERO_FLAG);
	}

    return 8;
}// RRC A

void CPU::rl8bitRegister(byte *reg) {
	byte lastBit = *reg & 0x80;
	*reg <<= 1;

	if (checkFlag(Flag::CARRY_FLAG)) {
		setBit(&AF.hi, 7);
	} else {
		clearBit(&AF.hi, 7);
	}

	clearFlags();
	if (lastBit != 0x00) {
		raiseFlag(Flag::CARRY_FLAG);
	}
	if (AF.hi == 0) {
		raiseFlag(ZERO_FLAG);
	}
}

short CPU::extendedOpcode0x10() {
    rl8bitRegister(&BC.hi);
    return 8;
}// rl B

short CPU::extendedOpcode0x11() {
    rl8bitRegister(&BC.low);
    return 8;
}// rl C

short CPU::extendedOpcode0x12() {
    rl8bitRegister(&DE.hi);
    return 8;
}// rl D

short CPU::extendedOpcode0x13() {
    rl8bitRegister(&DE.low);
    return 8;
}// rl E

short CPU::extendedOpcode0x14() {
    rl8bitRegister(&HL.hi);
    return 8;
}// rl H

short CPU::extendedOpcode0x15() {
    rl8bitRegister(&HL.low);
    return 8;
}// rl L

short CPU::extendedOpcode0x16() {
	byte reg = memory->read(HL.value);
	rl8bitRegister(&reg);
	memory->write(HL.value, reg);
    return 16;
}// rl (HL)

short CPU::extendedOpcode0x17() {

	byte bit = AF.hi & 0x80;

	byte carry = checkFlag(Flag::CARRY_FLAG) ? 0x01 : 0x00;
	AF.hi <<= carry;

	clearFlags();
	if (bit != 0x80) {
		raiseFlag(CARRY_FLAG);;
	}

	if (AF.hi == 0x0) {
		raiseFlag(ZERO_FLAG);
	}

	return 8;
}

void CPU::rr8bitRegister(byte *reg) {
	byte zeroBit = *reg & 0x01;
	*reg = *reg >> 1;

	if (checkFlag(Flag::CARRY_FLAG)) {
		setBit(reg, 7);
	} else {
		clearBit(reg, 7);
	}

	clearFlags();
	if (zeroBit == 0x01) {
		raiseFlag(Flag::CARRY_FLAG);
	}
	if (*reg == 0x00) {
		raiseFlag(Flag::ZERO_FLAG);
	}
}

short CPU::extendedOpcode0x18() {
    rr8bitRegister(&BC.hi);
    return 8;
}// rr B

short CPU::extendedOpcode0x19() {
    rr8bitRegister(&BC.low);
    return 8;
}// rr C

short CPU::extendedOpcode0x1A() {
    rr8bitRegister(&DE.hi);
    return 8;
}// rr D

short CPU::extendedOpcode0x1B() {
    rr8bitRegister(&DE.low);
    return 8;
}// rr E

short CPU::extendedOpcode0x1C() {
    rr8bitRegister(&HL.hi);
    return 8;
}// rr H

short CPU::extendedOpcode0x1D() {
    rr8bitRegister(&HL.low);
    return 8;
}// rr L

short CPU::extendedOpcode0x1E() {
	byte reg = memory->read(HL.value);
	rr8bitRegister(&reg);
    memory->write(HL.value, reg);
    return 16;
}// rr (HL)

short CPU::extendedOpcode0x1F() {
    rr8bitRegister(&AF.hi);
    return 8;
}// rr A

void CPU::sla8bitRegister(byte *reg) {
	byte lastBit = *reg & 0x80;
	*reg <<= 1;

	clearFlags();
	if (lastBit != 0x00) {
		raiseFlag(Flag::CARRY_FLAG);
	}
    if ( *reg == 0 ) {
        raiseFlag(ZERO_FLAG);
    }
}

short CPU::extendedOpcode0x20() {
    sla8bitRegister(&BC.hi);
    return 8;
}// sla B

short CPU::extendedOpcode0x21() {
    sla8bitRegister(&BC.low);
    return 8;
}// sla C

short CPU::extendedOpcode0x22() {
    sla8bitRegister(&DE.hi);
    return 8;
}// sla D

short CPU::extendedOpcode0x23() {
    sla8bitRegister(&DE.low);
    return 8;
}// sla E

short CPU::extendedOpcode0x24() {
    sla8bitRegister(&HL.hi);
    return 8;
}// sla H

short CPU::extendedOpcode0x25() {
    sla8bitRegister(&HL.low);
    return 8;
}// sla L

short CPU::extendedOpcode0x26() {
    byte reg = memory->read(HL.value);
	sla8bitRegister(&reg);
    memory->write(HL.value, reg);
    return 16;
}// sla (HL)

short CPU::extendedOpcode0x27() {
    sla8bitRegister(&AF.hi);
    return 8;
}// sla A

void CPU::sra8bitRegister(byte * reg) {
	byte firstBit = *reg & 0x01;
	byte lastBit = *reg & 0x80;

	*reg >>= 1;

	if (lastBit != 0x00) {
		setBit(reg, 7);
	} else {
		clearBit(reg, 7);
	}

	clearFlags();
	if (firstBit == 0x01) {
		raiseFlag(Flag::CARRY_FLAG);
	}
	if (*reg == 0x00) {
		raiseFlag(Flag::ZERO_FLAG);
	}
}

short CPU::extendedOpcode0x28() {
    sra8bitRegister(&BC.hi);
    return 8;
}// sra B

short CPU::extendedOpcode0x29() {
    sra8bitRegister(&BC.low);
    return 8;
}// sra C

short CPU::extendedOpcode0x2A() {
    sra8bitRegister(&DE.hi);
    return 8;
}// sra D

short CPU::extendedOpcode0x2B() {
    sra8bitRegister(&DE.low);
    return 8;
}// sra E

short CPU::extendedOpcode0x2C() {
    sra8bitRegister(&HL.hi);
    return 8;
}// sra H

short CPU::extendedOpcode0x2D(){
    sra8bitRegister(&HL.low);
    return 8;
}// sra L

short CPU::extendedOpcode0x2E() {
    byte data = memory->read(HL.value);
	sra8bitRegister(&data);
	memory->write(HL.value, data);
    return 16;
}// sra (HL)

short CPU::extendedOpcode0x2F() {
    sra8bitRegister(&AF.hi);
    return 8;
}// sra A

void CPU::swap8bitRegister(byte * reg) {
	clearFlags();

	*reg = (((*reg & 0xF0) >> 4) | ((*reg & 0x0F) << 4));

	if ( *reg == 0 ) {
        raiseFlag(ZERO_FLAG);
    }
}

short CPU::extendedOpcode0x30() {
    swap8bitRegister(&BC.hi);
    return 8;
}// swap B

short CPU::extendedOpcode0x31() {
    swap8bitRegister(&BC.low);
    return 8;
}// swap C

short CPU::extendedOpcode0x32() {
    swap8bitRegister(&DE.hi);
    return 8;
}// swap D

short CPU::extendedOpcode0x33() {
    swap8bitRegister(&DE.low);
    return 8;
}// swap E

short CPU::extendedOpcode0x34() {
    swap8bitRegister(&HL.hi);
    return 8;
}// swap H

short CPU::extendedOpcode0x35() {
    swap8bitRegister(&HL.low);
    return 8;
}// swap L

short CPU::extendedOpcode0x36() {
	clearFlags();
    byte data = memory->read(HL.value);
	data = (((data & 0xF0) >> 4) | ((data & 0x0F) << 4));

	if ( data == 0 ) {
        raiseFlag(ZERO_FLAG);
    }

    memory->write(HL.value, data);
    return 16;
}// swap (HL)

short CPU::extendedOpcode0x37() {
    swap8bitRegister(&AF.hi);
    return 8;
}// swap A

void CPU::srl8bitRegister(byte *reg) {
	byte firstBit = *reg & 0x01;
	*reg >>= 1;

	clearBit(reg, 7);

	clearFlags();
	if (firstBit == 0x01) {
        raiseFlag(CARRY_FLAG);
    }
	if (*reg == 0) {
        raiseFlag(ZERO_FLAG);
    }
}

short CPU::extendedOpcode0x38() {
    srl8bitRegister(&BC.hi);
    return 8;
}// SRL B

short CPU::extendedOpcode0x39() {
    srl8bitRegister(&BC.low);
    return 8;
}// SRL C

short CPU::extendedOpcode0x3A() {
    srl8bitRegister(&DE.hi);
    return 8;
}// SRL D

short CPU::extendedOpcode0x3B() {
    srl8bitRegister(&DE.low);
    return 8;
}// SRL E

short CPU::extendedOpcode0x3C() {
    srl8bitRegister(&HL.hi);
    return 8;
}// SRL H

short CPU::extendedOpcode0x3D() {
    srl8bitRegister(&HL.low);
    return 8;
}// SRL L

short CPU::extendedOpcode0x3E() {
    byte data = memory->read(HL.value);
	srl8bitRegister(&data);
	memory->write(HL.value, data);
    return 16;
}// SRL (HL)

short CPU::extendedOpcode0x3F() {
    srl8bitRegister(&AF.hi);
    return 8;
}// SRL A
<commit_msg>Fix RL, n operation<commit_after>#include "CPU.h"

short CPU::opcode0x07() {
	byte significantBit = AF.hi & 0x80;
	AF.hi <<= 1;

	if (checkFlag(Flag::CARRY_FLAG)) {
		setBit(&AF.hi, 0);
	}
	else {
		clearBit(&AF.hi, 0);
	}

	clearFlags();
	if (significantBit != 0) {
		raiseFlag(Flag::CARRY_FLAG);
	}

    return 4;
}

short CPU::opcode0x0F() {
	byte bitZero = AF.hi & 0x01;
	AF.hi >>= 1;

	clearFlags();
	if (bitZero == 0x01) {
		raiseFlag(Flag::CARRY_FLAG);
	}
	if (AF.hi == 0x00) {
		raiseFlag(Flag::ZERO_FLAG);
	}

    return 4;
}

short CPU::opcode0x17() {
	byte lastBit = AF.hi & 0x80;
	AF.hi <<= 1;

	if (checkFlag(Flag::CARRY_FLAG)) {
		setBit(&AF.hi, 0);
	} else {
		clearBit(&AF.hi, 0);
	}

	clearFlags();
	if (lastBit == 0x01) {
		raiseFlag(Flag::CARRY_FLAG);
	}
	if (AF.hi == 0) {
		raiseFlag(ZERO_FLAG);
	}
    return 4;
}// RLA

short CPU::opcode0x1F() {
	byte firstBit = AF.hi & 0x01;
	AF.hi >>= 1;

	if (checkFlag(Flag::CARRY_FLAG)) {
		setBit(&AF.hi, 7);
	} else {
		clearBit(&AF.hi, 7);
	}

	clearFlags();
	if (firstBit == 0x01) {
		raiseFlag(Flag::CARRY_FLAG);
	}
	return 4;
}// RR A

void CPU::rlc8bitRegister(byte * reg) {
	byte bit= *reg & 0x80;
	*reg <<= 1;

	clearFlags();
	if (bit == 0x01) {
		raiseFlag(Flag::CARRY_FLAG);
	}
	if (*reg == 0x00) {
		raiseFlag(ZERO_FLAG);
	}
}

short CPU::extendedOpcode0x00() {
    rlc8bitRegister(&BC.hi);
    return 8;
}// RLC B

short CPU::extendedOpcode0x01() {
    rlc8bitRegister(&BC.low);
    return 8;
}// RLC C

short CPU::extendedOpcode0x02() {
    rlc8bitRegister(&DE.hi);
    return 8;
}// RLC D

short CPU::extendedOpcode0x03() {
    rlc8bitRegister(&DE.low);
    return 8;
}// RLC E

short CPU::extendedOpcode0x04() {
    rlc8bitRegister(&HL.hi);
    return 8;
}// RLC H

short CPU::extendedOpcode0x05() {
    rlc8bitRegister(&HL.low);
    return 8;
}// RLC L

short CPU::extendedOpcode0x06() {
	byte reg = memory->read(HL.value) ;
	rlc8bitRegister(&reg);
	memory->write(HL.value, reg);

	return 16;
}// RLC (HL)

short CPU::extendedOpcode0x07() {
	byte significantBit = AF.hi & 0x80;
	AF.hi <<= 1;

	if (checkFlag(Flag::CARRY_FLAG)) {
		setBit(&AF.hi, 0);
	} else {
		clearBit(&AF.hi, 0);
	}

	clearFlags();
	if (significantBit != 0) {
		raiseFlag(Flag::CARRY_FLAG);
	}

	if (AF.hi == 0x00) {
		raiseFlag(Flag::ZERO_FLAG);
	}

    return 8;
}// RLC A

void CPU::rrc8bitRegister(byte *reg) {
	byte zeroBit = *reg & 0x01;
	*reg = *reg >> 1;

	clearFlags();
	if (zeroBit == 0x01) {
		raiseFlag(CARRY_FLAG);
	}
	if (*reg == 0) {
		raiseFlag(ZERO_FLAG);
    }
}

short CPU::extendedOpcode0x08() {
    rrc8bitRegister(&BC.hi);
    return 8;
}// RRC B

short CPU::extendedOpcode0x09() {
    rrc8bitRegister(&BC.low);
    return 8;
}// RRC C

short CPU::extendedOpcode0x0A() {
    rrc8bitRegister(&DE.hi);
    return 8;
}// RRC D

short CPU::extendedOpcode0x0B() {
    rrc8bitRegister(&DE.low);
    return 8;
}// RRC E

short CPU::extendedOpcode0x0C() {
    rrc8bitRegister(&HL.hi);
    return 8;
}// RRC H

short CPU::extendedOpcode0x0D() {
    rrc8bitRegister(&HL.low);
    return 8;
}// RRC L

short CPU::extendedOpcode0x0E() {
	byte reg = memory->read(HL.value) ;
	rrc8bitRegister(&reg);
	memory->write(HL.value, reg);
    return 16;
}// RRC (HL)

short CPU::extendedOpcode0x0F() {
	byte bit = AF.hi & 0x01;
	AF.hi >>= 1;

	clearFlags();
	if (bit == 0x01) {
		raiseFlag(Flag::CARRY_FLAG);
	}

	if (AF.hi == 0x00) {
		raiseFlag(Flag::ZERO_FLAG);
	}

    return 8;
}// RRC A

void CPU::rl8bitRegister(byte *reg) {
	byte significantBit = *reg & 0x80;
	*reg = *reg << 1;

	if (checkFlag(Flag::CARRY_FLAG)) {
		setBit(reg, 0);
	}
	else {
		clearBit(reg, 0);
	}

	clearFlags();
	if (significantBit != 0x00) {
		raiseFlag(Flag::CARRY_FLAG);
	}
	if (*reg == 0x00) {
		raiseFlag(Flag::ZERO_FLAG);
	}
}

short CPU::extendedOpcode0x10() {
    rl8bitRegister(&BC.hi);
    return 8;
}// rl B

short CPU::extendedOpcode0x11() {
    rl8bitRegister(&BC.low);
    return 8;
}// rl C

short CPU::extendedOpcode0x12() {
    rl8bitRegister(&DE.hi);
    return 8;
}// rl D

short CPU::extendedOpcode0x13() {
    rl8bitRegister(&DE.low);
    return 8;
}// rl E

short CPU::extendedOpcode0x14() {
    rl8bitRegister(&HL.hi);
    return 8;
}// rl H

short CPU::extendedOpcode0x15() {
    rl8bitRegister(&HL.low);
    return 8;
}// rl L

short CPU::extendedOpcode0x16() {
	byte reg = memory->read(HL.value);
	rl8bitRegister(&reg);
	memory->write(HL.value, reg);
    return 16;
}// rl (HL)

short CPU::extendedOpcode0x17() {
	rl8bitRegister(&AF.hi);
	return 8;
}

void CPU::rr8bitRegister(byte *reg) {
	byte zeroBit = *reg & 0x01;
	*reg = *reg >> 1;

	if (checkFlag(Flag::CARRY_FLAG)) {
		setBit(reg, 7);
	} else {
		clearBit(reg, 7);
	}

	clearFlags();
	if (zeroBit == 0x01) {
		raiseFlag(Flag::CARRY_FLAG);
	}
	if (*reg == 0x00) {
		raiseFlag(Flag::ZERO_FLAG);
	}
}

short CPU::extendedOpcode0x18() {
    rr8bitRegister(&BC.hi);
    return 8;
}// rr B

short CPU::extendedOpcode0x19() {
    rr8bitRegister(&BC.low);
    return 8;
}// rr C

short CPU::extendedOpcode0x1A() {
    rr8bitRegister(&DE.hi);
    return 8;
}// rr D

short CPU::extendedOpcode0x1B() {
    rr8bitRegister(&DE.low);
    return 8;
}// rr E

short CPU::extendedOpcode0x1C() {
    rr8bitRegister(&HL.hi);
    return 8;
}// rr H

short CPU::extendedOpcode0x1D() {
    rr8bitRegister(&HL.low);
    return 8;
}// rr L

short CPU::extendedOpcode0x1E() {
	byte reg = memory->read(HL.value);
	rr8bitRegister(&reg);
    memory->write(HL.value, reg);
    return 16;
}// rr (HL)

short CPU::extendedOpcode0x1F() {
    rr8bitRegister(&AF.hi);
    return 8;
}// rr A

void CPU::sla8bitRegister(byte *reg) {
	byte lastBit = *reg & 0x80;
	*reg <<= 1;

	clearFlags();
	if (lastBit != 0x00) {
		raiseFlag(Flag::CARRY_FLAG);
	}
    if ( *reg == 0 ) {
        raiseFlag(ZERO_FLAG);
    }
}

short CPU::extendedOpcode0x20() {
    sla8bitRegister(&BC.hi);
    return 8;
}// sla B

short CPU::extendedOpcode0x21() {
    sla8bitRegister(&BC.low);
    return 8;
}// sla C

short CPU::extendedOpcode0x22() {
    sla8bitRegister(&DE.hi);
    return 8;
}// sla D

short CPU::extendedOpcode0x23() {
    sla8bitRegister(&DE.low);
    return 8;
}// sla E

short CPU::extendedOpcode0x24() {
    sla8bitRegister(&HL.hi);
    return 8;
}// sla H

short CPU::extendedOpcode0x25() {
    sla8bitRegister(&HL.low);
    return 8;
}// sla L

short CPU::extendedOpcode0x26() {
    byte reg = memory->read(HL.value);
	sla8bitRegister(&reg);
    memory->write(HL.value, reg);
    return 16;
}// sla (HL)

short CPU::extendedOpcode0x27() {
    sla8bitRegister(&AF.hi);
    return 8;
}// sla A

void CPU::sra8bitRegister(byte * reg) {
	byte firstBit = *reg & 0x01;
	byte lastBit = *reg & 0x80;

	*reg >>= 1;

	if (lastBit != 0x00) {
		setBit(reg, 7);
	} else {
		clearBit(reg, 7);
	}

	clearFlags();
	if (firstBit == 0x01) {
		raiseFlag(Flag::CARRY_FLAG);
	}
	if (*reg == 0x00) {
		raiseFlag(Flag::ZERO_FLAG);
	}
}

short CPU::extendedOpcode0x28() {
    sra8bitRegister(&BC.hi);
    return 8;
}// sra B

short CPU::extendedOpcode0x29() {
    sra8bitRegister(&BC.low);
    return 8;
}// sra C

short CPU::extendedOpcode0x2A() {
    sra8bitRegister(&DE.hi);
    return 8;
}// sra D

short CPU::extendedOpcode0x2B() {
    sra8bitRegister(&DE.low);
    return 8;
}// sra E

short CPU::extendedOpcode0x2C() {
    sra8bitRegister(&HL.hi);
    return 8;
}// sra H

short CPU::extendedOpcode0x2D(){
    sra8bitRegister(&HL.low);
    return 8;
}// sra L

short CPU::extendedOpcode0x2E() {
    byte data = memory->read(HL.value);
	sra8bitRegister(&data);
	memory->write(HL.value, data);
    return 16;
}// sra (HL)

short CPU::extendedOpcode0x2F() {
    sra8bitRegister(&AF.hi);
    return 8;
}// sra A

void CPU::swap8bitRegister(byte * reg) {
	clearFlags();

	*reg = (((*reg & 0xF0) >> 4) | ((*reg & 0x0F) << 4));

	if ( *reg == 0 ) {
        raiseFlag(ZERO_FLAG);
    }
}

short CPU::extendedOpcode0x30() {
    swap8bitRegister(&BC.hi);
    return 8;
}// swap B

short CPU::extendedOpcode0x31() {
    swap8bitRegister(&BC.low);
    return 8;
}// swap C

short CPU::extendedOpcode0x32() {
    swap8bitRegister(&DE.hi);
    return 8;
}// swap D

short CPU::extendedOpcode0x33() {
    swap8bitRegister(&DE.low);
    return 8;
}// swap E

short CPU::extendedOpcode0x34() {
    swap8bitRegister(&HL.hi);
    return 8;
}// swap H

short CPU::extendedOpcode0x35() {
    swap8bitRegister(&HL.low);
    return 8;
}// swap L

short CPU::extendedOpcode0x36() {
	clearFlags();
    byte data = memory->read(HL.value);
	data = (((data & 0xF0) >> 4) | ((data & 0x0F) << 4));

	if ( data == 0 ) {
        raiseFlag(ZERO_FLAG);
    }

    memory->write(HL.value, data);
    return 16;
}// swap (HL)

short CPU::extendedOpcode0x37() {
    swap8bitRegister(&AF.hi);
    return 8;
}// swap A

void CPU::srl8bitRegister(byte *reg) {
	byte firstBit = *reg & 0x01;
	*reg >>= 1;

	clearBit(reg, 7);

	clearFlags();
	if (firstBit == 0x01) {
        raiseFlag(CARRY_FLAG);
    }
	if (*reg == 0) {
        raiseFlag(ZERO_FLAG);
    }
}

short CPU::extendedOpcode0x38() {
    srl8bitRegister(&BC.hi);
    return 8;
}// SRL B

short CPU::extendedOpcode0x39() {
    srl8bitRegister(&BC.low);
    return 8;
}// SRL C

short CPU::extendedOpcode0x3A() {
    srl8bitRegister(&DE.hi);
    return 8;
}// SRL D

short CPU::extendedOpcode0x3B() {
    srl8bitRegister(&DE.low);
    return 8;
}// SRL E

short CPU::extendedOpcode0x3C() {
    srl8bitRegister(&HL.hi);
    return 8;
}// SRL H

short CPU::extendedOpcode0x3D() {
    srl8bitRegister(&HL.low);
    return 8;
}// SRL L

short CPU::extendedOpcode0x3E() {
    byte data = memory->read(HL.value);
	srl8bitRegister(&data);
	memory->write(HL.value, data);
    return 16;
}// SRL (HL)

short CPU::extendedOpcode0x3F() {
    srl8bitRegister(&AF.hi);
    return 8;
}// SRL A
<|endoftext|>


<commit_before>//===--- SymbolCollector.cpp -------------------------------------*- C++-*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "SymbolCollector.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Index/IndexSymbol.h"
#include "clang/Index/USRGeneration.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"

namespace clang {
namespace clangd {

namespace {
// Make the Path absolute using the current working directory of the given
// SourceManager if the Path is not an absolute path.
//
// The Path can be a path relative to the build directory, or retrieved from
// the SourceManager.
std::string makeAbsolutePath(const SourceManager &SM, StringRef Path) {
  llvm::SmallString<128> AbsolutePath(Path);
  if (std::error_code EC =
          SM.getFileManager().getVirtualFileSystem()->makeAbsolute(
              AbsolutePath))
    llvm::errs() << "Warning: could not make absolute file: '" << EC.message()
                 << '\n';
  // Handle the symbolic link path case where the current working directory
  // (getCurrentWorkingDirectory) is a symlink./ We always want to the real
  // file path (instead of the symlink path) for the  C++ symbols.
  //
  // Consider the following example:
  //
  //   src dir: /project/src/foo.h
  //   current working directory (symlink): /tmp/build -> /project/src/
  //
  // The file path of Symbol is "/project/src/foo.h" instead of
  // "/tmp/build/foo.h"
  const DirectoryEntry *Dir = SM.getFileManager().getDirectory(
      llvm::sys::path::parent_path(AbsolutePath.str()));
  if (Dir) {
    StringRef DirName = SM.getFileManager().getCanonicalName(Dir);
    SmallVector<char, 128> AbsoluteFilename;
    llvm::sys::path::append(AbsoluteFilename, DirName,
                            llvm::sys::path::filename(AbsolutePath.str()));
    return llvm::StringRef(AbsoluteFilename.data(), AbsoluteFilename.size())
        .str();
  }
  return AbsolutePath.str();
}

// Split a qualified symbol name into scope and unqualified name, e.g. given
// "a::b::c", return {"a::b", "c"}. Scope is empty if it doesn't exist.
std::pair<llvm::StringRef, llvm::StringRef>
splitQualifiedName(llvm::StringRef QName) {
  assert(!QName.startswith("::") && "Qualified names should not start with ::");
  size_t Pos = QName.rfind("::");
  if (Pos == llvm::StringRef::npos)
    return {StringRef(), QName};
  return {QName.substr(0, Pos), QName.substr(Pos + 2)};
}

} // namespace

// Always return true to continue indexing.
bool SymbolCollector::handleDeclOccurence(
    const Decl *D, index::SymbolRoleSet Roles,
    ArrayRef<index::SymbolRelation> Relations, FileID FID, unsigned Offset,
    index::IndexDataConsumer::ASTNodeInfo ASTNode) {
  // FIXME: collect all symbol references.
  if (!(Roles & static_cast<unsigned>(index::SymbolRole::Declaration) ||
        Roles & static_cast<unsigned>(index::SymbolRole::Definition)))
    return true;

  if (const NamedDecl *ND = llvm::dyn_cast<NamedDecl>(D)) {
    // FIXME: Should we include the internal linkage symbols?
    if (!ND->hasExternalFormalLinkage() || ND->isInAnonymousNamespace())
      return true;

    llvm::SmallVector<char, 128> Buff;
    if (index::generateUSRForDecl(ND, Buff))
      return true;

    std::string USR(Buff.data(), Buff.size());
    auto ID = SymbolID(USR);
    if (Symbols.find(ID) != Symbols.end())
      return true;

    auto &SM = ND->getASTContext().getSourceManager();
    SymbolLocation Location = {
        makeAbsolutePath(SM, SM.getFilename(D->getLocation())),
        SM.getFileOffset(D->getLocStart()), SM.getFileOffset(D->getLocEnd())};
    std::string QName = ND->getQualifiedNameAsString();
    auto ScopeAndName = splitQualifiedName(QName);
    Symbols.insert({std::move(ID), ScopeAndName.second, ScopeAndName.first,
                    index::getSymbolInfo(D), std::move(Location)});
  }

  return true;
}

void SymbolCollector::finish() { Symbols.freeze(); }

} // namespace clangd
} // namespace clang
<commit_msg>[clangd] Fix use after free.<commit_after>//===--- SymbolCollector.cpp -------------------------------------*- C++-*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "SymbolCollector.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Index/IndexSymbol.h"
#include "clang/Index/USRGeneration.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"

namespace clang {
namespace clangd {

namespace {
// Make the Path absolute using the current working directory of the given
// SourceManager if the Path is not an absolute path.
//
// The Path can be a path relative to the build directory, or retrieved from
// the SourceManager.
std::string makeAbsolutePath(const SourceManager &SM, StringRef Path) {
  llvm::SmallString<128> AbsolutePath(Path);
  if (std::error_code EC =
          SM.getFileManager().getVirtualFileSystem()->makeAbsolute(
              AbsolutePath))
    llvm::errs() << "Warning: could not make absolute file: '" << EC.message()
                 << '\n';
  // Handle the symbolic link path case where the current working directory
  // (getCurrentWorkingDirectory) is a symlink./ We always want to the real
  // file path (instead of the symlink path) for the  C++ symbols.
  //
  // Consider the following example:
  //
  //   src dir: /project/src/foo.h
  //   current working directory (symlink): /tmp/build -> /project/src/
  //
  // The file path of Symbol is "/project/src/foo.h" instead of
  // "/tmp/build/foo.h"
  const DirectoryEntry *Dir = SM.getFileManager().getDirectory(
      llvm::sys::path::parent_path(AbsolutePath.str()));
  if (Dir) {
    StringRef DirName = SM.getFileManager().getCanonicalName(Dir);
    SmallVector<char, 128> AbsoluteFilename;
    llvm::sys::path::append(AbsoluteFilename, DirName,
                            llvm::sys::path::filename(AbsolutePath.str()));
    return llvm::StringRef(AbsoluteFilename.data(), AbsoluteFilename.size())
        .str();
  }
  return AbsolutePath.str();
}

// Split a qualified symbol name into scope and unqualified name, e.g. given
// "a::b::c", return {"a::b", "c"}. Scope is empty if it doesn't exist.
std::pair<llvm::StringRef, llvm::StringRef>
splitQualifiedName(llvm::StringRef QName) {
  assert(!QName.startswith("::") && "Qualified names should not start with ::");
  size_t Pos = QName.rfind("::");
  if (Pos == llvm::StringRef::npos)
    return {StringRef(), QName};
  return {QName.substr(0, Pos), QName.substr(Pos + 2)};
}

} // namespace

// Always return true to continue indexing.
bool SymbolCollector::handleDeclOccurence(
    const Decl *D, index::SymbolRoleSet Roles,
    ArrayRef<index::SymbolRelation> Relations, FileID FID, unsigned Offset,
    index::IndexDataConsumer::ASTNodeInfo ASTNode) {
  // FIXME: collect all symbol references.
  if (!(Roles & static_cast<unsigned>(index::SymbolRole::Declaration) ||
        Roles & static_cast<unsigned>(index::SymbolRole::Definition)))
    return true;

  if (const NamedDecl *ND = llvm::dyn_cast<NamedDecl>(D)) {
    // FIXME: Should we include the internal linkage symbols?
    if (!ND->hasExternalFormalLinkage() || ND->isInAnonymousNamespace())
      return true;

    llvm::SmallVector<char, 128> Buff;
    if (index::generateUSRForDecl(ND, Buff))
      return true;

    std::string USR(Buff.data(), Buff.size());
    auto ID = SymbolID(USR);
    if (Symbols.find(ID) != Symbols.end())
      return true;

    auto &SM = ND->getASTContext().getSourceManager();
    std::string FilePath =
        makeAbsolutePath(SM, SM.getFilename(D->getLocation()));
    SymbolLocation Location = {FilePath, SM.getFileOffset(D->getLocStart()),
                               SM.getFileOffset(D->getLocEnd())};
    std::string QName = ND->getQualifiedNameAsString();
    auto ScopeAndName = splitQualifiedName(QName);
    Symbols.insert({std::move(ID), ScopeAndName.second, ScopeAndName.first,
                    index::getSymbolInfo(D), std::move(Location)});
  }

  return true;
}

void SymbolCollector::finish() { Symbols.freeze(); }

} // namespace clangd
} // namespace clang
<|endoftext|>