<commit_before>/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009-2014 <NAME>

    This library 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 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "rawspeedconfig.h" // for WITH_SSE2
#include "common/RawImage.h"
#include "common/Memory.h"                // for alignedFree, alignedMalloc...
#include "decoders/RawDecoderException.h" // for ThrowRDE, RawDecoderException
#include "io/IOException.h"               // for IOException
#include "parsers/TiffParserException.h"  // for TiffParserException
#include <algorithm>                      // for min
#include <cassert>                        // for assert
#include <cmath>                          // for NAN
#include <cstdlib>                        // for free
#include <cstring>                        // for memset, memcpy, strdup
#include <limits>                         // for numeric_limits
#include <memory>                         // for unique_ptr

using std::fill_n;
using std::string;

namespace rawspeed {

RawImageData::RawImageData() : cfa(iPoint2D(0, 0)) {
  blackLevelSeparate.fill(-1);
}

RawImageData::RawImageData(const iPoint2D& _dim, uint32 _bpc, uint32 _cpp)
    : dim(_dim), isCFA(_cpp == 1), cfa(iPoint2D(0, 0)), cpp(_cpp) {
  assert(_bpc > 0);

  if (cpp > std::numeric_limits<decltype(bpp)>::max() / _bpc)
    ThrowRDE("Components-per-pixel is too large.");

  bpp = _bpc * _cpp;
  blackLevelSeparate.fill(-1);
  createData();
}

ImageMetaData::ImageMetaData() {
  subsampling.x = subsampling.y = 1;
  isoSpeed = 0;
  pixelAspectRatio = 1;
  fujiRotationPos = 0;
  fill_n(wbCoeffs, 4, NAN);
}

RawImageData::~RawImageData() {
  assert(dataRefCount == 0);
  mOffset = iPoint2D(0, 0);

  destroyData();
}


void RawImageData::createData() {
  static constexpr const auto alignment = 16;

  if (dim.x > 65535 || dim.y > 65535)
    ThrowRDE("Dimensions too large for allocation.");
  if (dim.x <= 0 || dim.y <= 0)
    ThrowRDE("Dimension of one sides is less than 1 - cannot allocate image.");
  if (data)
    ThrowRDE("Duplicate data allocation in createData.");

  // want each line to start at 16-byte aligned address
  pitch = roundUp(static_cast<size_t>(dim.x) * bpp, alignment);
  assert(isAligned(pitch, alignment));

#if defined(DEBUG) || __has_feature(address_sanitizer) ||                      \
    defined(__SANITIZE_ADDRESS__)
  // want to ensure that we have some padding
  pitch += alignment * alignment;
  assert(isAligned(pitch, alignment));
#endif

  padding = pitch - dim.x * bpp;

#if defined(DEBUG) || __has_feature(address_sanitizer) ||                      \
    defined(__SANITIZE_ADDRESS__)
  assert(padding > 0);
#endif

  data = alignedMallocArray<uchar8, alignment>(dim.y, pitch);

  if (!data)
    ThrowRDE("Memory Allocation failed.");

  uncropped_dim = dim;

#ifndef NDEBUG
  if (dim.y > 1) {
    // padding is the size of the area after last pixel of line n
    // and before the first pixel of line n+1
    assert(getData(dim.x - 1, 0) + bpp + padding == getData(0, 1));
  }

  for (int j = 0; j < dim.y; j++) {
    const uchar8* const line = getData(0, j);
    // each line is indeed 16-byte aligned
    assert(isAligned(line, alignment));
  }
#endif

  poisonPadding();
}

#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
void RawImageData::poisonPadding() {
  if (padding <= 0)
    return;

  for (int j = 0; j < uncropped_dim.y; j++) {
    const uchar8* const curr_line_end =
        getDataUncropped(uncropped_dim.x - 1, j) + bpp;

    // and now poison the padding.
    ASAN_POISON_MEMORY_REGION(curr_line_end, padding);
  }
}
#else
void __attribute__((const)) RawImageData::poisonPadding() {
  // if we are building without ASAN, then there is no need/way to poison.
  // however, i think it is better to have such an empty function rather
  // than making this whole function not exist in ASAN-less builds
}
#endif

#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
void RawImageData::unpoisonPadding() {
  if (padding <= 0)
    return;

  for (int j = 0; j < uncropped_dim.y; j++) {
    const uchar8* const curr_line_end =
        getDataUncropped(uncropped_dim.x - 1, j) + bpp;

    // and now unpoison the padding.
    ASAN_UNPOISON_MEMORY_REGION(curr_line_end, padding);
  }
}
#else
void __attribute__((const)) RawImageData::unpoisonPadding() {
  // if we are building without ASAN, then there is no need/way to poison.
  // however, i think it is better to have such an empty function rather
  // than making this whole function not exist in ASAN-less builds
}
#endif

#if __has_feature(memory_sanitizer) || defined(__SANITIZE_MEMORY__)
void RawImageData::checkRowIsInitialized(int row) {
  const auto rowsize = bpp * uncropped_dim.x;

  const uchar8* const curr_line = getDataUncropped(0, row);

  // and check that image line is initialized.
  // do note that we are avoiding padding here.
  MSAN_MEM_IS_INITIALIZED(curr_line, rowsize);
}
#else
void __attribute__((const)) RawImageData::checkRowIsInitialized(int row) {
  // if we are building without MSAN, then there is no way to check whether
  // the image row was fully initialized. however, i think it is better to
  // have such an empty function rather than making this whole function not
  // exist in MSAN-less builds
}
#endif

#if __has_feature(memory_sanitizer) || defined(__SANITIZE_MEMORY__)
void RawImageData::checkMemIsInitialized() {
  for (int j = 0; j < uncropped_dim.y; j++)
    checkRowIsInitialized(j);
}
#else
void __attribute__((const)) RawImageData::checkMemIsInitialized() {
  // if we are building without MSAN, then there is no way to check whether
  // the image data was fully initialized. however, i think it is better to
  // have such an empty function rather than making this whole function not
  // exist in MSAN-less builds
}
#endif
<commit_msg>GCC8 imbecility: RawImage: ‘const’ attribute on function returning ‘void’.<commit_after>/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009-2014 <NAME>

    This library 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 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "rawspeedconfig.h" // for WITH_SSE2
#include "common/RawImage.h"
#include "common/Memory.h"                // for alignedFree, alignedMalloc...
#include "decoders/RawDecoderException.h" // for ThrowRDE, RawDecoderException
#include "io/IOException.h"               // for IOException
#include "parsers/TiffParserException.h"  // for TiffParserException
#include <algorithm>                      // for min
#include <cassert>                        // for assert
#include <cmath>                          // for NAN
#include <cstdlib>                        // for free
#include <cstring>                        // for memset, memcpy, strdup
#include <limits>                         // for numeric_limits
#include <memory>                         // for unique_ptr

using std::fill_n;
using std::string;

namespace rawspeed {

RawImageData::RawImageData() : cfa(iPoint2D(0, 0)) {
  blackLevelSeparate.fill(-1);
}

RawImageData::RawImageData(const iPoint2D& _dim, uint32 _bpc, uint32 _cpp)
    : dim(_dim), isCFA(_cpp == 1), cfa(iPoint2D(0, 0)), cpp(_cpp) {
  assert(_bpc > 0);

  if (cpp > std::numeric_limits<decltype(bpp)>::max() / _bpc)
    ThrowRDE("Components-per-pixel is too large.");

  bpp = _bpc * _cpp;
  blackLevelSeparate.fill(-1);
  createData();
}

ImageMetaData::ImageMetaData() {
  subsampling.x = subsampling.y = 1;
  isoSpeed = 0;
  pixelAspectRatio = 1;
  fujiRotationPos = 0;
  fill_n(wbCoeffs, 4, NAN);
}

RawImageData::~RawImageData() {
  assert(dataRefCount == 0);
  mOffset = iPoint2D(0, 0);

  destroyData();
}


void RawImageData::createData() {
  static constexpr const auto alignment = 16;

  if (dim.x > 65535 || dim.y > 65535)
    ThrowRDE("Dimensions too large for allocation.");
  if (dim.x <= 0 || dim.y <= 0)
    ThrowRDE("Dimension of one sides is less than 1 - cannot allocate image.");
  if (data)
    ThrowRDE("Duplicate data allocation in createData.");

  // want each line to start at 16-byte aligned address
  pitch = roundUp(static_cast<size_t>(dim.x) * bpp, alignment);
  assert(isAligned(pitch, alignment));

#if defined(DEBUG) || __has_feature(address_sanitizer) ||                      \
    defined(__SANITIZE_ADDRESS__)
  // want to ensure that we have some padding
  pitch += alignment * alignment;
  assert(isAligned(pitch, alignment));
#endif

  padding = pitch - dim.x * bpp;

#if defined(DEBUG) || __has_feature(address_sanitizer) ||                      \
    defined(__SANITIZE_ADDRESS__)
  assert(padding > 0);
#endif

  data = alignedMallocArray<uchar8, alignment>(dim.y, pitch);

  if (!data)
    ThrowRDE("Memory Allocation failed.");

  uncropped_dim = dim;

#ifndef NDEBUG
  if (dim.y > 1) {
    // padding is the size of the area after last pixel of line n
    // and before the first pixel of line n+1
    assert(getData(dim.x - 1, 0) + bpp + padding == getData(0, 1));
  }

  for (int j = 0; j < dim.y; j++) {
    const uchar8* const line = getData(0, j);
    // each line is indeed 16-byte aligned
    assert(isAligned(line, alignment));
  }
#endif

  poisonPadding();
}

#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
void RawImageData::poisonPadding() {
  if (padding <= 0)
    return;

  for (int j = 0; j < uncropped_dim.y; j++) {
    const uchar8* const curr_line_end =
        getDataUncropped(uncropped_dim.x - 1, j) + bpp;

    // and now poison the padding.
    ASAN_POISON_MEMORY_REGION(curr_line_end, padding);
  }
}
#else
void RawImageData::poisonPadding() {
  // if we are building without ASAN, then there is no need/way to poison.
  // however, i think it is better to have such an empty function rather
  // than making this whole function not exist in ASAN-less builds
}
#endif

#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
void RawImageData::unpoisonPadding() {
  if (padding <= 0)
    return;

  for (int j = 0; j < uncropped_dim.y; j++) {
    const uchar8* const curr_line_end =
        getDataUncropped(uncropped_dim.x - 1, j) + bpp;

    // and now unpoison the padding.
    ASAN_UNPOISON_MEMORY_REGION(curr_line_end, padding);
  }
}
#else
void RawImageData::unpoisonPadding() {
  // if we are building without ASAN, then there is no need/way to poison.
  // however, i think it is better to have such an empty function rather
  // than making this whole function not exist in ASAN-less builds
}
#endif

#if __has_feature(memory_sanitizer) || defined(__SANITIZE_MEMORY__)
void RawImageData::checkRowIsInitialized(int row) {
  const auto rowsize = bpp * uncropped_dim.x;

  const uchar8* const curr_line = getDataUncropped(0, row);

  // and check that image line is initialized.
  // do note that we are avoiding padding here.
  MSAN_MEM_IS_INITIALIZED(curr_line, rowsize);
}
#else
void RawImageData::checkRowIsInitialized(int row) {
  // if we are building without MSAN, then there is no way to check whether
  // the image row was fully initialized. however, i think it is better to
  // have such an empty function rather than making this whole function not
  // exist in MSAN-less builds
}
#endif

#if __has_feature(memory_sanitizer) || defined(__SANITIZE_MEMORY__)
void RawImageData::checkMemIsInitialized() {
  for (int j = 0; j < uncropped_dim.y; j++)
    checkRowIsInitialized(j);
}
#else
void RawImageData::checkMemIsInitialized() {
  // if we are building without MSAN, then there is no way to check whether
  // the image data was fully initialized. however, i think it is better to
  // have such an empty function rather than making this whole function not
  // exist in MSAN-less builds
}
#endif

{'fraction_non_alphanumeric': 0.10377285703263638, 'fraction_numerical': 0.013347735514235013, 'mean_word_length': 3.2610124917817225, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6701510', 'n_tokens_mistral': 4220, 'n_tokens_neox': 4040, 'n_words': 1360}