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

#include "libmv/simple_pipeline/uncalibrated_reconstructor.h"

#include <cmath>
#include <cstdio>

#include "libmv/numeric/numeric.h"
#include "libmv/logging/logging.h"
#include "libmv/simple_pipeline/autocalibrate.h"
#include "libmv/simple_pipeline/camera_intrinsics.h"
#include "libmv/simple_pipeline/bundle.h"
#include "libmv/simple_pipeline/initialize_reconstruction.h"
#include "libmv/simple_pipeline/pipeline.h"
#include "libmv/simple_pipeline/reconstruction.h"

namespace libmv {

// Make a matrix to normalize image coordinates for "approximate" calibration.
// This takes the heursitic that the width and height of an image in pixels are
// approximately related to the focal length, and that the center of an image
// is the center of projection.
Mat3 NormalizerMatrix(int width, int height) {
  Mat3 M;
  double s = hypot(width, height);
  M << s, 0, width,
       0, s, height,
       0, 0, 2.0;
  M /= 2.0;
  return M.inverse();
}

// Normalizes a set of tracks according to the normalizer matrix.
void TransformTracks(Mat3 transform, const Tracks &tracks,
                     Tracks *normalized_tracks) {
  vector<Marker> markers = tracks.AllMarkers();
  for (int i = 0; i < markers.size(); ++i) {
    Vec3 a = Vec3(markers[i].x, markers[i].y, 1.0);
    Vec3 b = transform * a;
    markers[i].x = a(0) / a(2);
    markers[i].y = a(1) / a(2);
  }
  *normalized_tracks = Tracks(markers);
}

UncalibratedReconstructor::UncalibratedReconstructor(int width,
                                                     int height,
                                                     int keyframe1,
                                                     int keyframe2,
                                                     const Tracks &tracks) {
  // Save the raw tracks for later use.
  raw_tracks_ = tracks;

  LG << "Normalize all tracks with an approximate calibration.";
  getchar();
  Mat3 normalizer_matrix = NormalizerMatrix(width, height);
  TransformTracks(normalizer_matrix, tracks, &normalized_tracks_);

  LG << "Initialize the reconstruction; bundle (not implemented yet).";
  getchar();
  vector<Marker> initial_markers =
      normalized_tracks_.MarkersForTracksInBothImages(keyframe1, keyframe2);
  ProjectiveReconstructTwoFrames(initial_markers, &projective_reconstruction_);
  CameraIntrinsics default_intrinsics;
  ProjectiveReprojectionError(normalized_tracks_,
                              projective_reconstruction_,
                              default_intrinsics);

  LG << "Complete the projective reconstruction.";
  getchar();
  ReconstructionOptions reconstruction_options;
  reconstruction_options.success_threshold = 1e-3;
  reconstruction_options.use_fallback_reconstruction = true;
  ProjectiveCompleteReconstruction(reconstruction_options, normalized_tracks_, &projective_reconstruction_);
  ProjectiveReprojectionError(normalized_tracks_,
                              projective_reconstruction_,
                              default_intrinsics);

  LG << "Upgrade the reconstruction to Euclidean.";
  getchar();
  UpgradeProjectiveReconstructionToEuclidean(keyframe1,
                                             keyframe2,
                                             projective_reconstruction_,
                                             &euclidean_reconstruction_,
                                             &camera_intrinsics_);

  LG << "Multiply the normalizer matrix into the calibration matrix and "
     << "update the intrinsic parameters.";
  getchar();
  Mat3 K = camera_intrinsics_.K();
  camera_intrinsics_.SetK(K * NormalizerMatrix(width, height).inverse());
  camera_intrinsics_.SetImageSize(width, height);
  LG << "Got K matrix: " << camera_intrinsics_.K();

  LG << "Invert the intrinsics to get calibrated tracks.";
  getchar();
  InvertIntrinsicsForTracks(raw_tracks_,
                            camera_intrinsics_,
                            &calibrated_tracks_);

  LG << "Bundle adjust the final result.";
  getchar();
  EuclideanBundle(calibrated_tracks_, &euclidean_reconstruction_);
}

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

#include "libmv/simple_pipeline/uncalibrated_reconstructor.h"

#include <cmath>
#include <cstdio>

#include "libmv/numeric/numeric.h"
#include "libmv/logging/logging.h"
#include "libmv/simple_pipeline/autocalibrate.h"
#include "libmv/simple_pipeline/camera_intrinsics.h"
#include "libmv/simple_pipeline/bundle.h"
#include "libmv/simple_pipeline/initialize_reconstruction.h"
#include "libmv/simple_pipeline/pipeline.h"
#include "libmv/simple_pipeline/reconstruction.h"

namespace libmv {

// Make a matrix to normalize image coordinates for "approximate" calibration.
// This takes the heursitic that the width and height of an image in pixels are
// approximately related to the focal length, and that the center of an image
// is the center of projection.
Mat3 NormalizerMatrix(int width, int height) {
  Mat3 M;
  double s = hypot(width, height);
  M << s, 0, width,
       0, s, height,
       0, 0, 2.0;
  M /= 2.0;
  return M.inverse();
}

// Normalizes a set of tracks according to the normalizer matrix.
void TransformTracks(Mat3 transform, const Tracks &tracks,
                     Tracks *normalized_tracks) {
  vector<Marker> markers = tracks.AllMarkers();
  for (int i = 0; i < markers.size(); ++i) {
    Vec3 a = Vec3(markers[i].x, markers[i].y, 1.0);
    Vec3 b = transform * a;
    markers[i].x = b(0) / b(2);
    markers[i].y = b(1) / b(2);
  }
  *normalized_tracks = Tracks(markers);
}

UncalibratedReconstructor::UncalibratedReconstructor(int width,
                                                     int height,
                                                     int keyframe1,
                                                     int keyframe2,
                                                     const Tracks &tracks) {
  // Save the raw tracks for later use.
  raw_tracks_ = tracks;

  LG << "Normalize all tracks with an approximate calibration.";
  getchar();
  Mat3 normalizer_matrix = NormalizerMatrix(width, height);
  TransformTracks(normalizer_matrix, tracks, &normalized_tracks_);

  LG << "Initialize the reconstruction; bundle (not implemented yet).";
  getchar();
  vector<Marker> initial_markers =
      normalized_tracks_.MarkersForTracksInBothImages(keyframe1, keyframe2);
  ProjectiveReconstructTwoFrames(initial_markers, &projective_reconstruction_);
  CameraIntrinsics default_intrinsics;
  ProjectiveReprojectionError(normalized_tracks_,
                              projective_reconstruction_,
                              default_intrinsics);

  LG << "Complete the projective reconstruction.";
  getchar();
  ReconstructionOptions reconstruction_options;
  reconstruction_options.success_threshold = 1e-3;
  reconstruction_options.use_fallback_reconstruction = true;
  ProjectiveCompleteReconstruction(reconstruction_options, normalized_tracks_, &projective_reconstruction_);
  ProjectiveReprojectionError(normalized_tracks_,
                              projective_reconstruction_,
                              default_intrinsics);

  LG << "Upgrade the reconstruction to Euclidean.";
  getchar();
  UpgradeProjectiveReconstructionToEuclidean(keyframe1,
                                             keyframe2,
                                             projective_reconstruction_,
                                             &euclidean_reconstruction_,
                                             &camera_intrinsics_);

  LG << "Multiply the normalizer matrix into the calibration matrix and "
     << "update the intrinsic parameters.";
  getchar();
  Mat3 K = camera_intrinsics_.K();
  camera_intrinsics_.SetK(K * NormalizerMatrix(width, height).inverse());
  camera_intrinsics_.SetImageSize(width, height);
  LG << "Got K matrix: " << camera_intrinsics_.K();

  LG << "Invert the intrinsics to get calibrated tracks.";
  getchar();
  InvertIntrinsicsForTracks(raw_tracks_,
                            camera_intrinsics_,
                            &calibrated_tracks_);

  LG << "Bundle adjust the final result.";
  getchar();
  EuclideanBundle(calibrated_tracks_, &euclidean_reconstruction_);
}

}  // namespace libmv
<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(c), c is unique count of pattern

class Solution {
public:
    bool wordPattern(string pattern, string str) {
        int cnt = str.empty() ? 0 : 1;
        for (const auto& c : str) {
            if (c == ' ') {
                ++cnt;
            }
        }
        if (pattern.size() != cnt) {
            return false;
        }

        unordered_map<string, char> w2p;
        unordered_map<char, string> p2w;
        int i = 0, j = 0;
        for (const auto& p : pattern) {
            j = str.find(" ", i);
            if (j == string::npos) {
                j = str.length();
            }
            const string w = str.substr(i, j - i);
            if (!w2p.count(w) && !p2w.count(p)) {
                w2p[w] = p;
                p2w[p] = w;
            } else if (!w2p.count(w) || w2p[w] != p) {
                return false;
            }
            i = j + 1;
        }
        return true;
    }
};
<commit_msg>Update word-pattern.cpp<commit_after>// Time:  O(n)
// Space: O(c), c is unique count of pattern

class Solution {
public:
    bool wordPattern(string pattern, string str) {
        // Count the words.
        int cnt = str.empty() ? 0 : 1;
        for (const auto& c : str) {
            if (c == ' ') {
                ++cnt;
            }
        }
        if (pattern.size() != cnt) {
            return false;
        }

        unordered_map<string, char> w2p;
        unordered_map<char, string> p2w;
        int i = 0, j = 0;
        for (const auto& p : pattern) {
            // Get a word at a time without saving all the words.
            j = str.find(" ", i);
            if (j == string::npos) {
                j = str.length();
            }
            const string w = str.substr(i, j - i);

            if (!w2p.count(w) && !p2w.count(p)) {
                // Build mapping. Space: O(c)
                w2p[w] = p;
                p2w[p] = w;
            } else if (!w2p.count(w) || w2p[w] != p) {
                // Contradict mapping.
                return false;
            }
            i = j + 1;
        }
        return true;
    }
};
<|endoftext|>


<commit_before><commit_msg>Removed Throttle from drive.<commit_after><|endoftext|>


<commit_before><commit_msg>Include stream header files as appropriate.  Fixes bug 6765.<commit_after><|endoftext|>


<commit_before>/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2013. All Rights Reserved.  			      */
/* Open Source Software - may be modified and shared by FRC teams. The code   */
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
/*----------------------------------------------------------------------------*/
#pragma once

#ifdef __vxworks
#include <vxWorks.h>
#else
#include <stdint.h>
#endif
#include <cmath>

#include "Analog.hpp"
#include "Compressor.hpp"
#include "Digital.hpp"
#include "Solenoid.hpp"
#include "Notifier.hpp"
#include "Interrupts.hpp"
#include "Errors.hpp"
#include "PDP.hpp"

#include "Utilities.hpp"
#include "Semaphore.hpp"
#include "Task.hpp"

#define HAL_IO_CONFIG_DATA_SIZE 32
#define HAL_SYS_STATUS_DATA_SIZE 44
#define HAL_USER_STATUS_DATA_SIZE (984 - HAL_IO_CONFIG_DATA_SIZE - HAL_SYS_STATUS_DATA_SIZE)
#define HAL_USER_DS_LCD_DATA_SIZE 128

#define HALFRC_NetworkCommunication_DynamicType_DSEnhancedIO_Input 17
#define HALFRC_NetworkCommunication_DynamicType_DSEnhancedIO_Output 18
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Header 19
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Extra1 20
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Vertices1 21
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Extra2 22
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Vertices2 23
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Joystick 24
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Custom 25

namespace HALUsageReporting
{
	enum tResourceType
	{
		kResourceType_Controller,
		kResourceType_Module,
		kResourceType_Language,
		kResourceType_CANPlugin,
		kResourceType_Accelerometer,
		kResourceType_ADXL345,
		kResourceType_AnalogChannel,
		kResourceType_AnalogTrigger,
		kResourceType_AnalogTriggerOutput,
		kResourceType_CANJaguar,
		kResourceType_Compressor,
		kResourceType_Counter,
		kResourceType_Dashboard,
		kResourceType_DigitalInput,
		kResourceType_DigitalOutput,
		kResourceType_DriverStationCIO,
		kResourceType_DriverStationEIO,
		kResourceType_DriverStationLCD,
		kResourceType_Encoder,
		kResourceType_GearTooth,
		kResourceType_Gyro,
		kResourceType_I2C,
		kResourceType_Framework,
		kResourceType_Jaguar,
		kResourceType_Joystick,
		kResourceType_Kinect,
		kResourceType_KinectStick,
		kResourceType_PIDController,
		kResourceType_Preferences,
		kResourceType_PWM,
		kResourceType_Relay,
		kResourceType_RobotDrive,
		kResourceType_SerialPort,
		kResourceType_Servo,
		kResourceType_Solenoid,
		kResourceType_SPI,
		kResourceType_Task,
		kResourceType_Ultrasonic,
		kResourceType_Victor,
		kResourceType_Button,
		kResourceType_Command,
		kResourceType_AxisCamera,
		kResourceType_PCVideoServer,
		kResourceType_SmartDashboard,
		kResourceType_Talon,
		kResourceType_HiTechnicColorSensor,
		kResourceType_HiTechnicAccel,
		kResourceType_HiTechnicCompass,
		kResourceType_SRF08,
	};

	enum tInstances
	{
		kLanguage_LabVIEW = 1,
		kLanguage_CPlusPlus = 2,
		kLanguage_Java = 3,
		kLanguage_Python = 4,

		kCANPlugin_BlackJagBridge = 1,
		kCANPlugin_2CAN = 2,

		kFramework_Iterative = 1,
		kFramework_Simple = 2,

		kRobotDrive_ArcadeStandard = 1,
		kRobotDrive_ArcadeButtonSpin = 2,
		kRobotDrive_ArcadeRatioCurve = 3,
		kRobotDrive_Tank = 4,
		kRobotDrive_MecanumPolar = 5,
		kRobotDrive_MecanumCartesian = 6,

		kDriverStationCIO_Analog = 1,
		kDriverStationCIO_DigitalIn = 2,
		kDriverStationCIO_DigitalOut = 3,

		kDriverStationEIO_Acceleration = 1,
		kDriverStationEIO_AnalogIn = 2,
		kDriverStationEIO_AnalogOut = 3,
		kDriverStationEIO_Button = 4,
		kDriverStationEIO_LED = 5,
		kDriverStationEIO_DigitalIn = 6,
		kDriverStationEIO_DigitalOut = 7,
		kDriverStationEIO_FixedDigitalOut = 8,
		kDriverStationEIO_PWM = 9,
		kDriverStationEIO_Encoder = 10,
		kDriverStationEIO_TouchSlider = 11,

		kADXL345_SPI = 1,
		kADXL345_I2C = 2,

		kCommand_Scheduler = 1,

		kSmartDashboard_Instance = 1,
	};
}

struct HALCommonControlData
{
	uint16_t packetIndex;
	union
	{
		uint8_t control;
#ifndef __vxworks
		struct
		{
			uint8_t checkVersions :1;
			uint8_t test :1;
			uint8_t resync :1;
			uint8_t fmsAttached :1;
			uint8_t autonomous :1;
			uint8_t enabled :1;
			uint8_t notEStop :1;
			uint8_t reset :1;
		};
#else
		struct
		{
			uint8_t reset : 1;
			uint8_t notEStop : 1;
			uint8_t enabled : 1;
			uint8_t autonomous : 1;
			uint8_t fmsAttached:1;
			uint8_t resync : 1;
			uint8_t test :1;
			uint8_t checkVersions :1;
		};
#endif
	};
	uint8_t dsDigitalIn;
	uint16_t teamID;

	char dsID_Alliance;
	char dsID_Position;

	union
	{
		int8_t stick0Axes[6];
		struct
		{ // TODO: ???
			int8_t stick0Axis1;
			int8_t stick0Axis2;
			int8_t stick0Axis3;
			int8_t stick0Axis4;
			int8_t stick0Axis5;
			int8_t stick0Axis6;
		};
	};
	uint16_t stick0Buttons;		// Left-most 4 bits are unused

	union
	{
		int8_t stick1Axes[6];
		struct
		{ // TODO: ???
			int8_t stick1Axis1;
			int8_t stick1Axis2;
			int8_t stick1Axis3;
			int8_t stick1Axis4;
			int8_t stick1Axis5;
			int8_t stick1Axis6;
		};
	};
	uint16_t stick1Buttons;		// Left-most 4 bits are unused

	union
	{
		int8_t stick2Axes[6];
		struct
		{ // TODO: ???
			int8_t stick2Axis1;
			int8_t stick2Axis2;
			int8_t stick2Axis3;
			int8_t stick2Axis4;
			int8_t stick2Axis5;
			int8_t stick2Axis6;
		};
	};
	uint16_t stick2Buttons;		// Left-most 4 bits are unused

	union
	{
		int8_t stick3Axes[6];
		struct
		{ // TODO: ???
			int8_t stick3Axis1;
			int8_t stick3Axis2;
			int8_t stick3Axis3;
			int8_t stick3Axis4;
			int8_t stick3Axis5;
			int8_t stick3Axis6;
		};
	};
	uint16_t stick3Buttons;		// Left-most 4 bits are unused

	//Analog inputs are 10 bit right-justified
	uint16_t analog1;
	uint16_t analog2;
	uint16_t analog3;
	uint16_t analog4;

	uint64_t cRIOChecksum;
	uint32_t FPGAChecksum0;
	uint32_t FPGAChecksum1;
	uint32_t FPGAChecksum2;
	uint32_t FPGAChecksum3;

	char versionData[8];
};

inline float intToFloat(int value)
{
	return (float)value;
}

inline int floatToInt(float value)
{
	return round(value);
}

extern "C"
{
	extern const uint32_t dio_kNumSystems;
	extern const uint32_t solenoid_kNumDO7_0Elements;
	extern const uint32_t interrupt_kNumSystems;
	extern const uint32_t kSystemClockTicksPerMicrosecond;

	void* getPort(uint8_t pin);
	void* getPortWithModule(uint8_t module, uint8_t pin);
	const char* getHALErrorMessage(int32_t code);

	uint16_t getFPGAVersion(int32_t *status);
	uint32_t getFPGARevision(int32_t *status);
	uint32_t getFPGATime(int32_t *status);

	void setFPGALED(uint32_t state, int32_t *status);
	int32_t getFPGALED(int32_t *status);

	int HALSetErrorData(const char *errors, int errorsLength, int wait_ms);
	int HALSetUserDsLcdData(const char *userDsLcdData, int userDsLcdDataLength, int wait_ms);
	int HALOverrideIOConfig(const char *ioConfig, int wait_ms);
	int HALGetDynamicControlData(uint8_t type, char *dynamicData, int32_t maxLength, int wait_ms);
	int HALGetCommonControlData(HALCommonControlData *data, int wait_ms);
	void HALSetNewDataSem(pthread_mutex_t *);
	int HALSetStatusData(float battery, uint8_t dsDigitalOut, uint8_t updateNumber,
			const char *userDataHigh, int userDataHighLength, const char *userDataLow,
			int userDataLowLength, int wait_ms);

	int HALInitialize(int mode = 0);
	void HALNetworkCommunicationObserveUserProgramStarting();
	void HALNetworkCommunicationObserveUserProgramDisabled();
	void HALNetworkCommunicationObserveUserProgramAutonomous();
	void HALNetworkCommunicationObserveUserProgramTeleop();
	void HALNetworkCommunicationObserveUserProgramTest();

	uint32_t HALReport(uint8_t resource, uint8_t instanceNumber, uint8_t context = 0,
			const char *feature = NULL);
}

// TODO: HACKS for now...
extern "C"
{

	void NumericArrayResize();
	void RTSetCleanupProc();
	void EDVR_CreateReference();
	void Occur();
}

<commit_msg>Fixed a missing include<commit_after>/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2013. All Rights Reserved.  			      */
/* Open Source Software - may be modified and shared by FRC teams. The code   */
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
/*----------------------------------------------------------------------------*/
#pragma once

#ifdef __vxworks
#include <vxWorks.h>
#else
#include <stdint.h>
#endif
#include <cmath>

#include "Analog.hpp"
#include "Compressor.hpp"
#include "Digital.hpp"
#include "Solenoid.hpp"
#include "Notifier.hpp"
#include "Interrupts.hpp"
#include "Errors.hpp"

#include "Utilities.hpp"
#include "Semaphore.hpp"
#include "Task.hpp"

#define HAL_IO_CONFIG_DATA_SIZE 32
#define HAL_SYS_STATUS_DATA_SIZE 44
#define HAL_USER_STATUS_DATA_SIZE (984 - HAL_IO_CONFIG_DATA_SIZE - HAL_SYS_STATUS_DATA_SIZE)
#define HAL_USER_DS_LCD_DATA_SIZE 128

#define HALFRC_NetworkCommunication_DynamicType_DSEnhancedIO_Input 17
#define HALFRC_NetworkCommunication_DynamicType_DSEnhancedIO_Output 18
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Header 19
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Extra1 20
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Vertices1 21
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Extra2 22
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Vertices2 23
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Joystick 24
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Custom 25

namespace HALUsageReporting
{
	enum tResourceType
	{
		kResourceType_Controller,
		kResourceType_Module,
		kResourceType_Language,
		kResourceType_CANPlugin,
		kResourceType_Accelerometer,
		kResourceType_ADXL345,
		kResourceType_AnalogChannel,
		kResourceType_AnalogTrigger,
		kResourceType_AnalogTriggerOutput,
		kResourceType_CANJaguar,
		kResourceType_Compressor,
		kResourceType_Counter,
		kResourceType_Dashboard,
		kResourceType_DigitalInput,
		kResourceType_DigitalOutput,
		kResourceType_DriverStationCIO,
		kResourceType_DriverStationEIO,
		kResourceType_DriverStationLCD,
		kResourceType_Encoder,
		kResourceType_GearTooth,
		kResourceType_Gyro,
		kResourceType_I2C,
		kResourceType_Framework,
		kResourceType_Jaguar,
		kResourceType_Joystick,
		kResourceType_Kinect,
		kResourceType_KinectStick,
		kResourceType_PIDController,
		kResourceType_Preferences,
		kResourceType_PWM,
		kResourceType_Relay,
		kResourceType_RobotDrive,
		kResourceType_SerialPort,
		kResourceType_Servo,
		kResourceType_Solenoid,
		kResourceType_SPI,
		kResourceType_Task,
		kResourceType_Ultrasonic,
		kResourceType_Victor,
		kResourceType_Button,
		kResourceType_Command,
		kResourceType_AxisCamera,
		kResourceType_PCVideoServer,
		kResourceType_SmartDashboard,
		kResourceType_Talon,
		kResourceType_HiTechnicColorSensor,
		kResourceType_HiTechnicAccel,
		kResourceType_HiTechnicCompass,
		kResourceType_SRF08,
	};

	enum tInstances
	{
		kLanguage_LabVIEW = 1,
		kLanguage_CPlusPlus = 2,
		kLanguage_Java = 3,
		kLanguage_Python = 4,

		kCANPlugin_BlackJagBridge = 1,
		kCANPlugin_2CAN = 2,

		kFramework_Iterative = 1,
		kFramework_Simple = 2,

		kRobotDrive_ArcadeStandard = 1,
		kRobotDrive_ArcadeButtonSpin = 2,
		kRobotDrive_ArcadeRatioCurve = 3,
		kRobotDrive_Tank = 4,
		kRobotDrive_MecanumPolar = 5,
		kRobotDrive_MecanumCartesian = 6,

		kDriverStationCIO_Analog = 1,
		kDriverStationCIO_DigitalIn = 2,
		kDriverStationCIO_DigitalOut = 3,

		kDriverStationEIO_Acceleration = 1,
		kDriverStationEIO_AnalogIn = 2,
		kDriverStationEIO_AnalogOut = 3,
		kDriverStationEIO_Button = 4,
		kDriverStationEIO_LED = 5,
		kDriverStationEIO_DigitalIn = 6,
		kDriverStationEIO_DigitalOut = 7,
		kDriverStationEIO_FixedDigitalOut = 8,
		kDriverStationEIO_PWM = 9,
		kDriverStationEIO_Encoder = 10,
		kDriverStationEIO_TouchSlider = 11,

		kADXL345_SPI = 1,
		kADXL345_I2C = 2,

		kCommand_Scheduler = 1,

		kSmartDashboard_Instance = 1,
	};
}

struct HALCommonControlData
{
	uint16_t packetIndex;
	union
	{
		uint8_t control;
#ifndef __vxworks
		struct
		{
			uint8_t checkVersions :1;
			uint8_t test :1;
			uint8_t resync :1;
			uint8_t fmsAttached :1;
			uint8_t autonomous :1;
			uint8_t enabled :1;
			uint8_t notEStop :1;
			uint8_t reset :1;
		};
#else
		struct
		{
			uint8_t reset : 1;
			uint8_t notEStop : 1;
			uint8_t enabled : 1;
			uint8_t autonomous : 1;
			uint8_t fmsAttached:1;
			uint8_t resync : 1;
			uint8_t test :1;
			uint8_t checkVersions :1;
		};
#endif
	};
	uint8_t dsDigitalIn;
	uint16_t teamID;

	char dsID_Alliance;
	char dsID_Position;

	union
	{
		int8_t stick0Axes[6];
		struct
		{ // TODO: ???
			int8_t stick0Axis1;
			int8_t stick0Axis2;
			int8_t stick0Axis3;
			int8_t stick0Axis4;
			int8_t stick0Axis5;
			int8_t stick0Axis6;
		};
	};
	uint16_t stick0Buttons;		// Left-most 4 bits are unused

	union
	{
		int8_t stick1Axes[6];
		struct
		{ // TODO: ???
			int8_t stick1Axis1;
			int8_t stick1Axis2;
			int8_t stick1Axis3;
			int8_t stick1Axis4;
			int8_t stick1Axis5;
			int8_t stick1Axis6;
		};
	};
	uint16_t stick1Buttons;		// Left-most 4 bits are unused

	union
	{
		int8_t stick2Axes[6];
		struct
		{ // TODO: ???
			int8_t stick2Axis1;
			int8_t stick2Axis2;
			int8_t stick2Axis3;
			int8_t stick2Axis4;
			int8_t stick2Axis5;
			int8_t stick2Axis6;
		};
	};
	uint16_t stick2Buttons;		// Left-most 4 bits are unused

	union
	{
		int8_t stick3Axes[6];
		struct
		{ // TODO: ???
			int8_t stick3Axis1;
			int8_t stick3Axis2;
			int8_t stick3Axis3;
			int8_t stick3Axis4;
			int8_t stick3Axis5;
			int8_t stick3Axis6;
		};
	};
	uint16_t stick3Buttons;		// Left-most 4 bits are unused

	//Analog inputs are 10 bit right-justified
	uint16_t analog1;
	uint16_t analog2;
	uint16_t analog3;
	uint16_t analog4;

	uint64_t cRIOChecksum;
	uint32_t FPGAChecksum0;
	uint32_t FPGAChecksum1;
	uint32_t FPGAChecksum2;
	uint32_t FPGAChecksum3;

	char versionData[8];
};

inline float intToFloat(int value)
{
	return (float)value;
}

inline int floatToInt(float value)
{
	return round(value);
}

extern "C"
{
	extern const uint32_t dio_kNumSystems;
	extern const uint32_t solenoid_kNumDO7_0Elements;
	extern const uint32_t interrupt_kNumSystems;
	extern const uint32_t kSystemClockTicksPerMicrosecond;

	void* getPort(uint8_t pin);
	void* getPortWithModule(uint8_t module, uint8_t pin);
	const char* getHALErrorMessage(int32_t code);

	uint16_t getFPGAVersion(int32_t *status);
	uint32_t getFPGARevision(int32_t *status);
	uint32_t getFPGATime(int32_t *status);

	void setFPGALED(uint32_t state, int32_t *status);
	int32_t getFPGALED(int32_t *status);

	int HALSetErrorData(const char *errors, int errorsLength, int wait_ms);
	int HALSetUserDsLcdData(const char *userDsLcdData, int userDsLcdDataLength, int wait_ms);
	int HALOverrideIOConfig(const char *ioConfig, int wait_ms);
	int HALGetDynamicControlData(uint8_t type, char *dynamicData, int32_t maxLength, int wait_ms);
	int HALGetCommonControlData(HALCommonControlData *data, int wait_ms);
	void HALSetNewDataSem(pthread_mutex_t *);
	int HALSetStatusData(float battery, uint8_t dsDigitalOut, uint8_t updateNumber,
			const char *userDataHigh, int userDataHighLength, const char *userDataLow,
			int userDataLowLength, int wait_ms);

	int HALInitialize(int mode = 0);
	void HALNetworkCommunicationObserveUserProgramStarting();
	void HALNetworkCommunicationObserveUserProgramDisabled();
	void HALNetworkCommunicationObserveUserProgramAutonomous();
	void HALNetworkCommunicationObserveUserProgramTeleop();
	void HALNetworkCommunicationObserveUserProgramTest();

	uint32_t HALReport(uint8_t resource, uint8_t instanceNumber, uint8_t context = 0,
			const char *feature = NULL);
}

// TODO: HACKS for now...
extern "C"
{

	void NumericArrayResize();
	void RTSetCleanupProc();
	void EDVR_CreateReference();
	void Occur();
}

<|endoftext|>


<commit_before>#include <stdlib.h>
#include <assert.h>
#include <stdexcept>
#include <string.h>
#include <algorithm>
#include <cmath>
#include "bitmap/Bitmap.h"

using namespace Framework;

CBitmap::CBitmap(const CBitmap& src)
{
	CopyFrom(src);
}

CBitmap::CBitmap(CBitmap&& src)
{
	MoveFrom(std::move(src));
}

CBitmap::CBitmap(unsigned int nWidth, unsigned int nHeight, unsigned int nBPP)
{
	Allocate(nWidth, nHeight, nBPP);
}

CBitmap::~CBitmap()
{
	Reset();
}

CBitmap& CBitmap::operator =(const CBitmap& src)
{
	if(&src == this)
	{
		return (*this);
	}

	CopyFrom(src);

	return (*this);
}

CBitmap& CBitmap::operator =(CBitmap&& src)
{
	Reset();
	MoveFrom(std::move(src));
	return (*this);
}

void CBitmap::Allocate(unsigned int width, unsigned int height, unsigned int bpp)
{
	assert(m_pixels == nullptr);

	m_width		= width;
	m_height	= height;
	m_bpp		= bpp;
	m_pixels	= new uint8[GetPixelsSize()];
}

void CBitmap::Reset()
{
	delete [] m_pixels;
	m_pixels = nullptr;

	m_width = 0;
	m_height = 0;
	m_bpp = 0;
}

bool CBitmap::IsEmpty() const
{
	return m_pixels == nullptr;
}

uint8* CBitmap::GetPixels() const
{
	assert(m_pixels != nullptr);
	return m_pixels;
}

CColor CBitmap::GetPixel(unsigned int x, unsigned int y) const
{
	if(m_pixels == nullptr)
	{
		return CColor(0, 0, 0, 0);
	}

	if(x > m_width) return CColor(0, 0, 0, 0);
	if(y > m_height) return CColor(0, 0, 0, 0);

	uint8* pixelPtr = (m_pixels + (GetPitch() * y) + (GetPixelSize() * x));
	switch(m_bpp)
	{
	case 32:
		return CColor(pixelPtr[0], pixelPtr[1], pixelPtr[2], pixelPtr[3]);
		break;
	case 24:
		return CColor(pixelPtr[0], pixelPtr[1], pixelPtr[2], 0);
		break;
	default:
		throw std::runtime_error("Unknown bit depth.");
		break;
	}
}

void CBitmap::SetPixel(unsigned int x, unsigned int y, const CColor& color)
{
	if(m_pixels == nullptr)
	{
		return;
	}

	if(x > m_width) return;
	if(y > m_height) return;

	uint8* pixelPtr = (m_pixels + (GetPitch() * y) + (GetPixelSize() * x));
	switch(m_bpp)
	{
	case 32:
		pixelPtr[0] = color.r;
		pixelPtr[1] = color.g;
		pixelPtr[2] = color.b;
		pixelPtr[3] = color.a;
		break;
	default:
		throw std::runtime_error("Unknown bit depth.");
		break;
	}
}

unsigned int CBitmap::GetWidth() const
{
	return m_width;
}

unsigned int CBitmap::GetHeight() const
{
	return m_height;
}

unsigned int CBitmap::GetBitsPerPixel() const
{
	return m_bpp;
}

unsigned int CBitmap::GetPixelSize() const
{
	return (m_bpp + 7) / 8;
}

unsigned int CBitmap::GetPixelsSize() const
{
	unsigned int nSize = m_width * m_height * m_bpp;
	return ((nSize + 7) / 8);
}

unsigned int CBitmap::GetPitch() const
{
	return (((m_width * m_bpp) + 7) / 8);
}

void CBitmap::Blit(const CBitmap& Src, unsigned int nLeft, unsigned int nTop)
{
	CBitmap& Dst = (*this);

	unsigned int nWidth		= Src.GetWidth();
	unsigned int nHeight	= Src.GetHeight();

	if(&Dst == &Src)
	{
		throw std::exception();
	}

	if((nWidth + nLeft) > Dst.GetWidth())
	{
		throw std::exception();
	}

	if((nHeight + nTop) > Dst.GetHeight())
	{
		throw std::exception();
	}

	if(Dst.GetBitsPerPixel() != Src.GetBitsPerPixel())
	{
		throw std::exception();
	}

	size_t nSrcPitch = Src.GetPitch();
	size_t nDstPitch = Dst.GetPitch();
	uint8* pSrcPtr = Src.GetPixels();
	uint8* pDstPtr = Dst.GetPixels() + (nDstPitch * nTop) + (nLeft * Dst.GetBitsPerPixel() / 8);

	for(unsigned int j = 0; j < nHeight; j++)
	{
		memcpy(pDstPtr, pSrcPtr, nSrcPitch);
		pDstPtr += nDstPitch;
		pSrcPtr += nSrcPitch;
	}
}

CBitmap CBitmap::AddAlphaChannel(uint8 alphaValue) const
{
	assert(m_bpp == 24);
	CBitmap result(m_width, m_height, 32);

	uint32 pixelCount = m_width * m_height;
	for(uint32 i = 0; i < pixelCount; i++)
	{
		result.m_pixels[(i * 4) + 0] = m_pixels[(i * 3) + 0];
		result.m_pixels[(i * 4) + 1] = m_pixels[(i * 3) + 1];
		result.m_pixels[(i * 4) + 2] = m_pixels[(i * 3) + 2];
		result.m_pixels[(i * 4) + 3] = alphaValue;
	}

	return result;
}

CBitmap CBitmap::Resize(unsigned int newWidth, unsigned int newHeight) const
{
	if(IsEmpty()) return CBitmap();

	CBitmap result(newWidth, newHeight, m_bpp);

	unsigned int srcPitch = GetPitch();
	unsigned int dstPitch = result.GetPitch();
	unsigned int pixelSize = GetPixelSize();

	auto dstPtr = result.m_pixels;
	for(unsigned int y = 0; y < newHeight; y++)
	{
		unsigned int sampleY = (y * m_height) / newHeight;
		for(unsigned int x = 0; x < newWidth; x++)
		{
			unsigned int sampleX = (x * m_width) / newWidth;

			for(unsigned int i = 0; i < pixelSize; i++)
			{
				uint8 pixelSrc = m_pixels[(sampleX * pixelSize) + (sampleY * srcPitch) + i];
				dstPtr[(x * pixelSize) + i] = pixelSrc;
			}
		}
		dstPtr += dstPitch;
	}

	return result;
}

CBitmap CBitmap::ResizeCanvas(unsigned int newWidth, unsigned int newHeight) const
{
	if(IsEmpty()) return CBitmap();

	CBitmap result(newWidth, newHeight, m_bpp);

	unsigned int srcPitch = GetPitch();
	unsigned int dstPitch = result.GetPitch();
	unsigned int copyPitch = std::min<unsigned int>(srcPitch, dstPitch);
	unsigned int copyHeight = std::min<unsigned int>(newHeight, m_height);

	auto srcPtr = m_pixels;
	auto dstPtr = result.m_pixels;
	for(unsigned int y = 0; y < copyHeight; y++)
	{
		memcpy(dstPtr, srcPtr, copyPitch);
		srcPtr += srcPitch;
		dstPtr += dstPitch;
	}

	return result;
}

void CBitmap::DrawLine(int x1, int y1, int x2, int y2, const CColor& color)
{
	uint32 convertedColor = (color.r << 0) | (color.g << 8) | (color.b << 16) | (color.a << 24);

	assert(m_bpp == 32);

	if((x1 < 0) && (x2 < 0)) return;
	if((x1 >= m_width) && (x2 >= m_width)) return;

	if((y1 < 0) && (y2 < 0)) return;
	if((y1 >= m_height) && (y2 >= m_height)) return;

	int dx = x2 - x1;
	int dy = y2 - y1;

	if((dx == 0) && (dy == 0)) return;

	float error = 0;

	if(abs(dy) < abs(dx))
	{
		float deltaErr = fabs(static_cast<float>(dy) / static_cast<float>(dx));
		if(x1 > x2)
		{
			std::swap(x1, x2);
			std::swap(y1, y2);
			dy = -dy;
		}
		int y = y1;
		for(int x = x1; x <= x2; x++)
		{
			if(
				(x >= 0) && (x < m_width) &&
				(y >= 0) && (y < m_height)
				)
			{
				reinterpret_cast<uint32*>(m_pixels)[x + (y * m_width)] = convertedColor;
			}
			error = error + deltaErr;
			if(error >= 0.5)
			{
				y += (dy >= 0) ? 1 : -1;
				error -= 1.0f;
			}
		}
	}
	else
	{
		float deltaErr = fabs(static_cast<float>(dx) / static_cast<float>(dy));
		if(y1 > y2)
		{
			std::swap(x1, x2);
			std::swap(y1, y2);
			dx = -dx;
		}
		int x = x1;
		for(int y = y1; y <= y2; y++)
		{
			if(
				(x >= 0) && (x < m_width) &&
				(y >= 0) && (y < m_height)
				)
			{
				reinterpret_cast<uint32*>(m_pixels)[x + (y * m_width)] = convertedColor;
			}
			error = error + deltaErr;
			if(error >= 0.5)
			{
				x += (dx >= 0) ? 1 : -1;
				error -= 1.0f;
			}
		}
	}
}

void CBitmap::CopyFrom(const CBitmap& src)
{
	if(src.GetPixelsSize() != GetPixelsSize())
	{
		m_pixels = reinterpret_cast<uint8*>(realloc(m_pixels, src.GetPixelsSize()));
	}

	m_width		= src.GetWidth();
	m_height	= src.GetHeight();
	m_bpp		= src.GetBitsPerPixel();

	if(GetPixelsSize() != 0)
	{
		memcpy(m_pixels, src.GetPixels(), GetPixelsSize());
	}
}

void CBitmap::MoveFrom(CBitmap&& src)
{
	std::swap(src.m_pixels, m_pixels);
	std::swap(src.m_width,  m_width);
	std::swap(src.m_height, m_height);
	std::swap(src.m_bpp,    m_bpp);
}
<commit_msg>Add support for other bit depths in Get/SetPixel.<commit_after>#include <stdlib.h>
#include <assert.h>
#include <stdexcept>
#include <string.h>
#include <algorithm>
#include <cmath>
#include "bitmap/Bitmap.h"

using namespace Framework;

CBitmap::CBitmap(const CBitmap& src)
{
	CopyFrom(src);
}

CBitmap::CBitmap(CBitmap&& src)
{
	MoveFrom(std::move(src));
}

CBitmap::CBitmap(unsigned int nWidth, unsigned int nHeight, unsigned int nBPP)
{
	Allocate(nWidth, nHeight, nBPP);
}

CBitmap::~CBitmap()
{
	Reset();
}

CBitmap& CBitmap::operator =(const CBitmap& src)
{
	if(&src == this)
	{
		return (*this);
	}

	CopyFrom(src);

	return (*this);
}

CBitmap& CBitmap::operator =(CBitmap&& src)
{
	Reset();
	MoveFrom(std::move(src));
	return (*this);
}

void CBitmap::Allocate(unsigned int width, unsigned int height, unsigned int bpp)
{
	assert(m_pixels == nullptr);

	m_width		= width;
	m_height	= height;
	m_bpp		= bpp;
	m_pixels	= new uint8[GetPixelsSize()];
}

void CBitmap::Reset()
{
	delete [] m_pixels;
	m_pixels = nullptr;

	m_width = 0;
	m_height = 0;
	m_bpp = 0;
}

bool CBitmap::IsEmpty() const
{
	return m_pixels == nullptr;
}

uint8* CBitmap::GetPixels() const
{
	assert(m_pixels != nullptr);
	return m_pixels;
}

CColor CBitmap::GetPixel(unsigned int x, unsigned int y) const
{
	if(m_pixels == nullptr)
	{
		return CColor(0, 0, 0, 0);
	}

	if(x > m_width) return CColor(0, 0, 0, 0);
	if(y > m_height) return CColor(0, 0, 0, 0);

	uint8* pixelPtr = (m_pixels + (GetPitch() * y) + (GetPixelSize() * x));
	switch(m_bpp)
	{
	case 8:
		return CColor(pixelPtr[0], 0, 0, 0);
		break;
	case 24:
		return CColor(pixelPtr[0], pixelPtr[1], pixelPtr[2], 0);
		break;
	case 32:
		return CColor(pixelPtr[0], pixelPtr[1], pixelPtr[2], pixelPtr[3]);
		break;
	default:
		throw std::runtime_error("Unknown bit depth.");
		break;
	}
}

void CBitmap::SetPixel(unsigned int x, unsigned int y, const CColor& color)
{
	if(m_pixels == nullptr)
	{
		return;
	}

	if(x > m_width) return;
	if(y > m_height) return;

	uint8* pixelPtr = (m_pixels + (GetPitch() * y) + (GetPixelSize() * x));
	switch(m_bpp)
	{
	case 8:
		pixelPtr[0] = color.r;
		break;
	case 24:
		pixelPtr[0] = color.r;
		pixelPtr[1] = color.g;
		pixelPtr[2] = color.b;
		break;
	case 32:
		pixelPtr[0] = color.r;
		pixelPtr[1] = color.g;
		pixelPtr[2] = color.b;
		pixelPtr[3] = color.a;
		break;
	default:
		throw std::runtime_error("Unknown bit depth.");
		break;
	}
}

unsigned int CBitmap::GetWidth() const
{
	return m_width;
}

unsigned int CBitmap::GetHeight() const
{
	return m_height;
}

unsigned int CBitmap::GetBitsPerPixel() const
{
	return m_bpp;
}

unsigned int CBitmap::GetPixelSize() const
{
	return (m_bpp + 7) / 8;
}

unsigned int CBitmap::GetPixelsSize() const
{
	unsigned int nSize = m_width * m_height * m_bpp;
	return ((nSize + 7) / 8);
}

unsigned int CBitmap::GetPitch() const
{
	return (((m_width * m_bpp) + 7) / 8);
}

void CBitmap::Blit(const CBitmap& Src, unsigned int nLeft, unsigned int nTop)
{
	CBitmap& Dst = (*this);

	unsigned int nWidth		= Src.GetWidth();
	unsigned int nHeight	= Src.GetHeight();

	if(&Dst == &Src)
	{
		throw std::exception();
	}

	if((nWidth + nLeft) > Dst.GetWidth())
	{
		throw std::exception();
	}

	if((nHeight + nTop) > Dst.GetHeight())
	{
		throw std::exception();
	}

	if(Dst.GetBitsPerPixel() != Src.GetBitsPerPixel())
	{
		throw std::exception();
	}

	size_t nSrcPitch = Src.GetPitch();
	size_t nDstPitch = Dst.GetPitch();
	uint8* pSrcPtr = Src.GetPixels();
	uint8* pDstPtr = Dst.GetPixels() + (nDstPitch * nTop) + (nLeft * Dst.GetBitsPerPixel() / 8);

	for(unsigned int j = 0; j < nHeight; j++)
	{
		memcpy(pDstPtr, pSrcPtr, nSrcPitch);
		pDstPtr += nDstPitch;
		pSrcPtr += nSrcPitch;
	}
}

CBitmap CBitmap::AddAlphaChannel(uint8 alphaValue) const
{
	assert(m_bpp == 24);
	CBitmap result(m_width, m_height, 32);

	uint32 pixelCount = m_width * m_height;
	for(uint32 i = 0; i < pixelCount; i++)
	{
		result.m_pixels[(i * 4) + 0] = m_pixels[(i * 3) + 0];
		result.m_pixels[(i * 4) + 1] = m_pixels[(i * 3) + 1];
		result.m_pixels[(i * 4) + 2] = m_pixels[(i * 3) + 2];
		result.m_pixels[(i * 4) + 3] = alphaValue;
	}

	return result;
}

CBitmap CBitmap::Resize(unsigned int newWidth, unsigned int newHeight) const
{
	if(IsEmpty()) return CBitmap();

	CBitmap result(newWidth, newHeight, m_bpp);

	unsigned int srcPitch = GetPitch();
	unsigned int dstPitch = result.GetPitch();
	unsigned int pixelSize = GetPixelSize();

	auto dstPtr = result.m_pixels;
	for(unsigned int y = 0; y < newHeight; y++)
	{
		unsigned int sampleY = (y * m_height) / newHeight;
		for(unsigned int x = 0; x < newWidth; x++)
		{
			unsigned int sampleX = (x * m_width) / newWidth;

			for(unsigned int i = 0; i < pixelSize; i++)
			{
				uint8 pixelSrc = m_pixels[(sampleX * pixelSize) + (sampleY * srcPitch) + i];
				dstPtr[(x * pixelSize) + i] = pixelSrc;
			}
		}
		dstPtr += dstPitch;
	}

	return result;
}

CBitmap CBitmap::ResizeCanvas(unsigned int newWidth, unsigned int newHeight) const
{
	if(IsEmpty()) return CBitmap();

	CBitmap result(newWidth, newHeight, m_bpp);

	unsigned int srcPitch = GetPitch();
	unsigned int dstPitch = result.GetPitch();
	unsigned int copyPitch = std::min<unsigned int>(srcPitch, dstPitch);
	unsigned int copyHeight = std::min<unsigned int>(newHeight, m_height);

	auto srcPtr = m_pixels;
	auto dstPtr = result.m_pixels;
	for(unsigned int y = 0; y < copyHeight; y++)
	{
		memcpy(dstPtr, srcPtr, copyPitch);
		srcPtr += srcPitch;
		dstPtr += dstPitch;
	}

	return result;
}

void CBitmap::DrawLine(int x1, int y1, int x2, int y2, const CColor& color)
{
	uint32 convertedColor = (color.r << 0) | (color.g << 8) | (color.b << 16) | (color.a << 24);

	assert(m_bpp == 32);

	if((x1 < 0) && (x2 < 0)) return;
	if((x1 >= m_width) && (x2 >= m_width)) return;

	if((y1 < 0) && (y2 < 0)) return;
	if((y1 >= m_height) && (y2 >= m_height)) return;

	int dx = x2 - x1;
	int dy = y2 - y1;

	if((dx == 0) && (dy == 0)) return;

	float error = 0;

	if(abs(dy) < abs(dx))
	{
		float deltaErr = fabs(static_cast<float>(dy) / static_cast<float>(dx));
		if(x1 > x2)
		{
			std::swap(x1, x2);
			std::swap(y1, y2);
			dy = -dy;
		}
		int y = y1;
		for(int x = x1; x <= x2; x++)
		{
			if(
				(x >= 0) && (x < m_width) &&
				(y >= 0) && (y < m_height)
				)
			{
				reinterpret_cast<uint32*>(m_pixels)[x + (y * m_width)] = convertedColor;
			}
			error = error + deltaErr;
			if(error >= 0.5)
			{
				y += (dy >= 0) ? 1 : -1;
				error -= 1.0f;
			}
		}
	}
	else
	{
		float deltaErr = fabs(static_cast<float>(dx) / static_cast<float>(dy));
		if(y1 > y2)
		{
			std::swap(x1, x2);
			std::swap(y1, y2);
			dx = -dx;
		}
		int x = x1;
		for(int y = y1; y <= y2; y++)
		{
			if(
				(x >= 0) && (x < m_width) &&
				(y >= 0) && (y < m_height)
				)
			{
				reinterpret_cast<uint32*>(m_pixels)[x + (y * m_width)] = convertedColor;
			}
			error = error + deltaErr;
			if(error >= 0.5)
			{
				x += (dx >= 0) ? 1 : -1;
				error -= 1.0f;
			}
		}
	}
}

void CBitmap::CopyFrom(const CBitmap& src)
{
	if(src.GetPixelsSize() != GetPixelsSize())
	{
		m_pixels = reinterpret_cast<uint8*>(realloc(m_pixels, src.GetPixelsSize()));
	}

	m_width		= src.GetWidth();
	m_height	= src.GetHeight();
	m_bpp		= src.GetBitsPerPixel();

	if(GetPixelsSize() != 0)
	{
		memcpy(m_pixels, src.GetPixels(), GetPixelsSize());
	}
}

void CBitmap::MoveFrom(CBitmap&& src)
{
	std::swap(src.m_pixels, m_pixels);
	std::swap(src.m_width,  m_width);
	std::swap(src.m_height, m_height);
	std::swap(src.m_bpp,    m_bpp);
}
<|endoftext|>


<commit_before>// VsJoint.cpp: implementation of the VsJoint class.
//
//////////////////////////////////////////////////////////////////////

#include "StdAfx.h"
#include "VsBody.h"
#include "VsJoint.h"
#include "VsRigidBody.h"
#include "VsSimulator.h"
#include "VsDragger.h"

namespace VortexAnimatSim
{
	namespace Environment
	{

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

VsJoint::VsJoint()
{
	m_bMotorOn = FALSE;
}

VsJoint::~VsJoint()
{
}

VxVector3 VsJoint::NormalizeAxis(CStdFPoint vLocalRot)
{
	osg::Vec3 vPosN(1, 0, 0);
	CStdFPoint vMatrixPos(0, 0, 0);

	osg::Matrix osgMT = SetupMatrix(vMatrixPos, vLocalRot);

	osg::Vec3 vNorm = vPosN * osgMT;

	VxVector3 axis((double) vNorm[0], (double) vNorm[1], (double) vNorm[2]);

	return axis;
}

void VsJoint::EnableMotor(BOOL bOn, float fltDesiredVelocity, float fltMaxForce)
{
  if (m_vxJoint)
	{
		if(bOn)
		{
			if(m_vxJoint->getControl(m_iCoordID) != Vx::VxConstraint::CoordinateControlEnum::kControlMotorized)
				m_vxJoint->setControl(m_iCoordID, Vx::VxConstraint::CoordinateControlEnum::kControlMotorized);

			m_vxJoint->setMotorDesiredVelocity(m_iCoordID, fltDesiredVelocity);

			//DWC Need to fix the stuff to set the min/max force for motor. Does not work right now.
			//m_vxJoint->setMotorParameters(m_iCoordID, fltDesiredVelocity, -fltMaxForce, fltMaxForce);
			//turn on the motor (disabling lock or free mode)
		}
		else
			m_vxJoint->setControl(m_iCoordID, Vx::VxConstraint::CoordinateControlEnum::kControlFree);

		m_bMotorOn = bOn;
	}
}

void VsJoint::EnableLock(BOOL bOn, float fltPosition, float fltMaxLockForce)
{
	if (m_vxJoint)
	{
		if(bOn)
		{
			//set the lock parameters
			m_vxJoint->setLockParameters(m_iCoordID, fltPosition, -fltMaxLockForce, fltMaxLockForce);
			//turn on the lock (disabling motorized or free mode)
			m_vxJoint->setControl(m_iCoordID, VxConstraint::CoordinateControlEnum::kControlLocked);
		}
		else if (m_bMotorOn)
			EnableMotor(TRUE, 0, fltMaxLockForce);
		else
			m_vxJoint->setControl(m_iCoordID, VxConstraint::CoordinateControlEnum::kControlFree);
	}
}

void VsJoint::SetVelocity(float fltDesiredVelocity, float fltMaxForce)
{
	m_vxJoint->setMotorDesiredVelocity(m_iCoordID, fltDesiredVelocity);
}

void VsJoint::UpdatePosition()
{
	Vx::VxReal3 vPos;
	m_vxJoint->getPartAttachmentPosition(0, vPos);

	m_lpThis->AbsolutePosition(vPos[0], vPos[0], vPos[0]);
	m_lpThis->ReportWorldPosition(m_lpThis->AbsolutePosition() * m_lpThis->GetSimulator()->DistanceUnits());
}

void VsJoint::Physics_CollectBodyData(Simulator *lpSim)
{
	if(m_lpThis && m_vxJoint)
	{
		VsRigidBody *lpVsParent = dynamic_cast<VsRigidBody *>(m_lpThis->Parent());
		if(!lpVsParent)
			THROW_ERROR(Vs_Err_lUnableToConvertToVsRigidBody, Vs_Err_strUnableToConvertToVsRigidBody);

		UpdatePosition();

		if(m_vxJoint->isAngular(m_iCoordID) == true)
		{
			m_lpThisJoint->JointPosition(m_vxJoint->getCoordinateCurrentPosition (m_iCoordID));
			m_lpThisJoint->JointVelocity(m_vxJoint->getCoordinateVelocity (m_iCoordID));
			m_lpThisJoint->JointForce(m_vxJoint->getCoordinateForce (m_iCoordID));
		}
		else
		{
			float fltDistanceUnits = lpSim->DistanceUnits();
			float fltMassUnits = lpSim->MassUnits();

			m_lpThisJoint->JointPosition(m_vxJoint->getCoordinateCurrentPosition (m_iCoordID) * fltDistanceUnits);
			m_lpThisJoint->JointVelocity(m_vxJoint->getCoordinateVelocity(m_iCoordID) * fltDistanceUnits);
			m_lpThisJoint->JointForce(m_vxJoint->getCoordinateForce(m_iCoordID) * fltMassUnits * fltDistanceUnits);
		}
	}
}

float *VsJoint::Physics_GetDataPointer(string strDataType)
{
	string strType = Std_CheckString(strDataType);
	Joint *lpBody = dynamic_cast<Joint *>(this);

	return NULL;
}

osg::Group *VsJoint::ParentOSG(Simulator *lpSim, Structure *lpStructure)
{
	RigidBody *lpParent = m_lpThis->Parent();
	if(lpParent)
	{
		VsRigidBody *lpVsParent = dynamic_cast<VsRigidBody *>(lpParent);
		if(lpVsParent) return lpVsParent->GetMatrixTransform();
	}

	return NULL;
}

osg::Group *VsJoint::ChildOSG(Simulator *lpSim, Structure *lpStructure)
{
	RigidBody *lpChild = m_lpThisJoint->Child();
	if(lpChild)
	{
		VsRigidBody *lpVsChild = dynamic_cast<VsRigidBody *>(lpChild);
		if(lpVsChild) return lpVsChild->GetMatrixTransform();
	}

	return NULL;
}

void VsJoint::SetupGraphics(Simulator *lpSim, Structure *lpStructure)
{
}

void VsJoint::SetupPhysics(Simulator *lpSim, Structure *lpStructure)
{
}

void VsJoint::Initialize(Simulator *lpSim, Structure *lpStructure)
{
}

void VsJoint::SetBody(Simulator *lpSim, Structure *lpStructure)
{
}

void VsJoint::LocalMatrix(osg::Matrix osgLocalMT)
{
	m_osgLocalMatrix = osgLocalMT;
	m_osgFinalMatrix = m_osgLocalMatrix * m_osgChildOffsetMatrix;
}

void VsJoint::ChildOffsetMatrix(osg::Matrix osgMT)
{
	m_osgChildOffsetMatrix = osgMT;
	m_osgFinalMatrix = m_osgLocalMatrix * m_osgChildOffsetMatrix;
	m_osgChildOffsetMT->setMatrix(m_osgChildOffsetMatrix);
}

void VsJoint::UpdatePositionAndRotationFromMatrix()
{
	VsBody::UpdatePositionAndRotationFromMatrix();
	SetupPhysics(m_lpThis->GetSimulator(), m_lpThis->GetStructure());
}

void VsJoint::Physics_UpdateMatrix()
{
	LocalMatrix(SetupMatrix(m_lpThis->LocalPosition(), m_lpThis->Rotation()));
	m_osgMT->setMatrix(m_osgLocalMatrix);
	m_osgDragger->SetupMatrix();

	//Now lets get the localmatrix from the child object and use that for our offsetmatrix
	VsBody *lpVsChild = dynamic_cast<VsBody *>(m_lpThisJoint->Child());
	if(lpVsChild)
		ChildOffsetMatrix(lpVsChild->LocalMatrix());

	//If we are here then we did not have a physics component, just and OSG one.
	CStdFPoint vPos = VsBody::GetOSGWorldCoords();
	vPos.ClearNearZero();
	m_lpThis->AbsolutePosition(vPos.x, vPos.y, vPos.z);
	m_lpThis->ReportWorldPosition(m_lpThis->AbsolutePosition() * m_lpThis->GetSimulator()->DistanceUnits());
}

void VsJoint::BuildLocalMatrix(CStdFPoint localPos, CStdFPoint localRot, string strName)
{
	if(!m_osgMT.valid())
	{
		m_osgMT = new osgManipulator::Selection;
		m_osgMT->setName(strName + "_MT");
	}

	if(!m_osgChildOffsetMT.valid())
	{
		m_osgChildOffsetMT = new osg::MatrixTransform;
		m_osgChildOffsetMT->setName(strName + "ChildOffsetMT");
	}

	if(!m_osgRoot.valid())
	{
		m_osgRoot = new osg::Group;
		m_osgRoot->setName(strName + "_Root");
	}

	m_osgChildOffsetMT->addChild(m_osgMT.get());
	m_osgRoot->addChild(m_osgChildOffsetMT.get());

	LocalMatrix(SetupMatrix(localPos, localRot));

	//set the matrix to the matrix transform node
	m_osgMT->setMatrix(m_osgLocalMatrix);
	m_osgMT->setName(strName.c_str());

	//Now lets get the localmatrix from the child object and use that for our offsetmatrix
	VsBody *lpVsChild = dynamic_cast<VsBody *>(m_lpThisJoint->Child());
	if(lpVsChild)
		ChildOffsetMatrix(lpVsChild->LocalMatrix());

	//First create the node group. The reason for this is so that we can add other decorated groups on to this node.
	//This is used to add the selected overlays.
	if(!m_osgNodeGroup.valid())
	{
		m_osgNodeGroup = new osg::Group();
		m_osgNodeGroup->addChild(m_osgNode.get());
		m_osgNodeGroup->setName(strName + "_NodeGroup");

		m_osgMT->addChild(m_osgNodeGroup.get());

		CreateSelectedGraphics(strName);
	}
}

void VsJoint::Physics_ResetSimulation(Simulator *lpSim, Structure *lpStructure)
{
	if(m_vxJoint)
	{
		m_vxJoint->resetDynamics();

		UpdatePosition();
		m_lpThisJoint->JointPosition(0);
		m_lpThisJoint->JointVelocity(0);
		m_lpThisJoint->JointForce(0);
	}
}

	}			// Environment
}				//VortexAnimatSim<commit_msg>Fixed a bug where the m_vxJoint param was not initialized to NULL. Caused the program to crash.<commit_after>// VsJoint.cpp: implementation of the VsJoint class.
//
//////////////////////////////////////////////////////////////////////

#include "StdAfx.h"
#include "VsBody.h"
#include "VsJoint.h"
#include "VsRigidBody.h"
#include "VsSimulator.h"
#include "VsDragger.h"

namespace VortexAnimatSim
{
	namespace Environment
	{

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

VsJoint::VsJoint()
{
	m_bMotorOn = FALSE;
	m_vxJoint = NULL;
}

VsJoint::~VsJoint()
{
}

VxVector3 VsJoint::NormalizeAxis(CStdFPoint vLocalRot)
{
	osg::Vec3 vPosN(1, 0, 0);
	CStdFPoint vMatrixPos(0, 0, 0);

	osg::Matrix osgMT = SetupMatrix(vMatrixPos, vLocalRot);

	osg::Vec3 vNorm = vPosN * osgMT;

	VxVector3 axis((double) vNorm[0], (double) vNorm[1], (double) vNorm[2]);

	return axis;
}

void VsJoint::EnableMotor(BOOL bOn, float fltDesiredVelocity, float fltMaxForce)
{
  if (m_vxJoint)
	{
		if(bOn)
		{
			if(m_vxJoint->getControl(m_iCoordID) != Vx::VxConstraint::CoordinateControlEnum::kControlMotorized)
				m_vxJoint->setControl(m_iCoordID, Vx::VxConstraint::CoordinateControlEnum::kControlMotorized);

			m_vxJoint->setMotorDesiredVelocity(m_iCoordID, fltDesiredVelocity);

			//DWC Need to fix the stuff to set the min/max force for motor. Does not work right now.
			//m_vxJoint->setMotorParameters(m_iCoordID, fltDesiredVelocity, -fltMaxForce, fltMaxForce);
			//turn on the motor (disabling lock or free mode)
		}
		else
			m_vxJoint->setControl(m_iCoordID, Vx::VxConstraint::CoordinateControlEnum::kControlFree);

		m_bMotorOn = bOn;
	}
}

void VsJoint::EnableLock(BOOL bOn, float fltPosition, float fltMaxLockForce)
{
	if (m_vxJoint)
	{
		if(bOn)
		{
			//set the lock parameters
			m_vxJoint->setLockParameters(m_iCoordID, fltPosition, -fltMaxLockForce, fltMaxLockForce);
			//turn on the lock (disabling motorized or free mode)
			m_vxJoint->setControl(m_iCoordID, VxConstraint::CoordinateControlEnum::kControlLocked);
		}
		else if (m_bMotorOn)
			EnableMotor(TRUE, 0, fltMaxLockForce);
		else
			m_vxJoint->setControl(m_iCoordID, VxConstraint::CoordinateControlEnum::kControlFree);
	}
}

void VsJoint::SetVelocity(float fltDesiredVelocity, float fltMaxForce)
{
	m_vxJoint->setMotorDesiredVelocity(m_iCoordID, fltDesiredVelocity);
}

void VsJoint::UpdatePosition()
{
	Vx::VxReal3 vPos;
	m_vxJoint->getPartAttachmentPosition(0, vPos);

	m_lpThis->AbsolutePosition(vPos[0], vPos[0], vPos[0]);
	m_lpThis->ReportWorldPosition(m_lpThis->AbsolutePosition() * m_lpThis->GetSimulator()->DistanceUnits());
}

void VsJoint::Physics_CollectBodyData(Simulator *lpSim)
{
	if(m_lpThis && m_vxJoint)
	{
		VsRigidBody *lpVsParent = dynamic_cast<VsRigidBody *>(m_lpThis->Parent());
		if(!lpVsParent)
			THROW_ERROR(Vs_Err_lUnableToConvertToVsRigidBody, Vs_Err_strUnableToConvertToVsRigidBody);

		UpdatePosition();

		if(m_vxJoint->isAngular(m_iCoordID) == true)
		{
			m_lpThisJoint->JointPosition(m_vxJoint->getCoordinateCurrentPosition (m_iCoordID));
			m_lpThisJoint->JointVelocity(m_vxJoint->getCoordinateVelocity (m_iCoordID));
			m_lpThisJoint->JointForce(m_vxJoint->getCoordinateForce (m_iCoordID));
		}
		else
		{
			float fltDistanceUnits = lpSim->DistanceUnits();
			float fltMassUnits = lpSim->MassUnits();

			m_lpThisJoint->JointPosition(m_vxJoint->getCoordinateCurrentPosition (m_iCoordID) * fltDistanceUnits);
			m_lpThisJoint->JointVelocity(m_vxJoint->getCoordinateVelocity(m_iCoordID) * fltDistanceUnits);
			m_lpThisJoint->JointForce(m_vxJoint->getCoordinateForce(m_iCoordID) * fltMassUnits * fltDistanceUnits);
		}
	}
}

float *VsJoint::Physics_GetDataPointer(string strDataType)
{
	string strType = Std_CheckString(strDataType);
	Joint *lpBody = dynamic_cast<Joint *>(this);

	return NULL;
}

osg::Group *VsJoint::ParentOSG(Simulator *lpSim, Structure *lpStructure)
{
	RigidBody *lpParent = m_lpThis->Parent();
	if(lpParent)
	{
		VsRigidBody *lpVsParent = dynamic_cast<VsRigidBody *>(lpParent);
		if(lpVsParent) return lpVsParent->GetMatrixTransform();
	}

	return NULL;
}

osg::Group *VsJoint::ChildOSG(Simulator *lpSim, Structure *lpStructure)
{
	RigidBody *lpChild = m_lpThisJoint->Child();
	if(lpChild)
	{
		VsRigidBody *lpVsChild = dynamic_cast<VsRigidBody *>(lpChild);
		if(lpVsChild) return lpVsChild->GetMatrixTransform();
	}

	return NULL;
}

void VsJoint::SetupGraphics(Simulator *lpSim, Structure *lpStructure)
{
}

void VsJoint::SetupPhysics(Simulator *lpSim, Structure *lpStructure)
{
}

void VsJoint::Initialize(Simulator *lpSim, Structure *lpStructure)
{
}

void VsJoint::SetBody(Simulator *lpSim, Structure *lpStructure)
{
}

void VsJoint::LocalMatrix(osg::Matrix osgLocalMT)
{
	m_osgLocalMatrix = osgLocalMT;
	m_osgFinalMatrix = m_osgLocalMatrix * m_osgChildOffsetMatrix;
}

void VsJoint::ChildOffsetMatrix(osg::Matrix osgMT)
{
	m_osgChildOffsetMatrix = osgMT;
	m_osgFinalMatrix = m_osgLocalMatrix * m_osgChildOffsetMatrix;
	m_osgChildOffsetMT->setMatrix(m_osgChildOffsetMatrix);
}

void VsJoint::UpdatePositionAndRotationFromMatrix()
{
	VsBody::UpdatePositionAndRotationFromMatrix();
	SetupPhysics(m_lpThis->GetSimulator(), m_lpThis->GetStructure());
}

void VsJoint::Physics_UpdateMatrix()
{
	LocalMatrix(SetupMatrix(m_lpThis->LocalPosition(), m_lpThis->Rotation()));
	m_osgMT->setMatrix(m_osgLocalMatrix);
	m_osgDragger->SetupMatrix();

	//Now lets get the localmatrix from the child object and use that for our offsetmatrix
	VsBody *lpVsChild = dynamic_cast<VsBody *>(m_lpThisJoint->Child());
	if(lpVsChild)
		ChildOffsetMatrix(lpVsChild->LocalMatrix());

	//If we are here then we did not have a physics component, just and OSG one.
	CStdFPoint vPos = VsBody::GetOSGWorldCoords();
	vPos.ClearNearZero();
	m_lpThis->AbsolutePosition(vPos.x, vPos.y, vPos.z);
	m_lpThis->ReportWorldPosition(m_lpThis->AbsolutePosition() * m_lpThis->GetSimulator()->DistanceUnits());
}

void VsJoint::BuildLocalMatrix(CStdFPoint localPos, CStdFPoint localRot, string strName)
{
	if(!m_osgMT.valid())
	{
		m_osgMT = new osgManipulator::Selection;
		m_osgMT->setName(strName + "_MT");
	}

	if(!m_osgChildOffsetMT.valid())
	{
		m_osgChildOffsetMT = new osg::MatrixTransform;
		m_osgChildOffsetMT->setName(strName + "ChildOffsetMT");
	}

	if(!m_osgRoot.valid())
	{
		m_osgRoot = new osg::Group;
		m_osgRoot->setName(strName + "_Root");
	}

	m_osgChildOffsetMT->addChild(m_osgMT.get());
	m_osgRoot->addChild(m_osgChildOffsetMT.get());

	LocalMatrix(SetupMatrix(localPos, localRot));

	//set the matrix to the matrix transform node
	m_osgMT->setMatrix(m_osgLocalMatrix);
	m_osgMT->setName(strName.c_str());

	//Now lets get the localmatrix from the child object and use that for our offsetmatrix
	VsBody *lpVsChild = dynamic_cast<VsBody *>(m_lpThisJoint->Child());
	if(lpVsChild)
		ChildOffsetMatrix(lpVsChild->LocalMatrix());

	//First create the node group. The reason for this is so that we can add other decorated groups on to this node.
	//This is used to add the selected overlays.
	if(!m_osgNodeGroup.valid())
	{
		m_osgNodeGroup = new osg::Group();
		m_osgNodeGroup->addChild(m_osgNode.get());
		m_osgNodeGroup->setName(strName + "_NodeGroup");

		m_osgMT->addChild(m_osgNodeGroup.get());

		CreateSelectedGraphics(strName);
	}
}

void VsJoint::Physics_ResetSimulation(Simulator *lpSim, Structure *lpStructure)
{
	if(m_vxJoint)
	{
		m_vxJoint->resetDynamics();

		UpdatePosition();
		m_lpThisJoint->JointPosition(0);
		m_lpThisJoint->JointVelocity(0);
		m_lpThisJoint->JointForce(0);
	}
}

	}			// Environment
}				//VortexAnimatSim<|endoftext|>


<commit_before>#include <algorithm>
#include <map>
#include <string>
#include <limits>

#include "Prefetch.h"
#include "CodeGen_Internal.h"
#include "IRMutator.h"
#include "IROperator.h"
#include "Bounds.h"
#include "Scope.h"
#include "Simplify.h"
#include "Substitute.h"
#include "Util.h"

namespace Halide {
namespace Internal {

using std::map;
using std::string;
using std::vector;
using std::stack;

int dbg_prefetch  = 1;
int dbg_prefetch2 = 2;

class InjectPrefetch : public IRMutator {
public:
    InjectPrefetch(const map<string, Function> &e)
        : env(e) { }
private:
    const map<string, Function> &env;
    Scope<Interval> scope;

private:
    using IRMutator::visit;

    // Strip down the tuple name, e.g. f.*.var into f
    string tuple_func(const string &name) {
        vector<string> v = split_string(name, ".");
        internal_assert(v.size() > 0);
        return v[0];
    }

    // Strip down the tuple name, e.g. f.*.var into var
    string tuple_var(const string &name) {
        vector<string> v = split_string(name, ".");
        internal_assert(v.size() > 0);
        return v[v.size()-1];
    }

    Function get_func(const string &name) {
        map<string, Function>::const_iterator iter = env.find(name);
        internal_assert(iter != env.end()) << "Realize node refers to function not in environment.\n";
        return iter->second;
    }

    void visit(const Let *op) {
        Interval in = bounds_of_expr_in_scope(op->value, scope);
        scope.push(op->name, in);
        IRMutator::visit(op);
        scope.pop(op->name);
    }
    void visit(const LetStmt *op) {
        Interval in = bounds_of_expr_in_scope(op->value, scope);
        scope.push(op->name, in);
        IRMutator::visit(op);
        scope.pop(op->name);
    }

    void visit(const For *op) {
        Stmt body = op->body;

        string func_name = tuple_func(op->name);
        string var_name  = tuple_var(op->name);
        vector<Prefetch> &prefetches = get_func(func_name).schedule().prefetches();

        if (prefetches.empty()) {
            debug(dbg_prefetch2) << "InjectPrefetch: " << op->name << " " << func_name << " " << var_name;
            debug(dbg_prefetch2) << " No prefetch\n";
        } else {
            debug(dbg_prefetch) << "InjectPrefetch: " << op->name << " " << func_name << " " << var_name;
            debug(dbg_prefetch) << " Found prefetch directive(s)\n";
        }

        // Todo: Check to see if op->name is in prefetches
        for (const Prefetch &p : prefetches) {
            debug(dbg_prefetch) << "InjectPrefetch: check var:" << p.var
                               << " offset:" << p.offset << "\n";
            if (p.var == var_name) {
                debug(dbg_prefetch) << " prefetch on " << var_name << "\n";
                string fetch_func = "halide.hexagon.l2fetch.Rtt";

                // Interval prein(op->name, op->name);
                // Add in prefetch offset
                Expr var = Variable::make(Int(32), op->name);
                Interval prein(var + p.offset, var + p.offset);
                scope.push(op->name, prein);

                map<string, Box> boxes;
                boxes = boxes_required(body, scope);

                debug(dbg_prefetch) << "  boxes required:\n";
                for (auto &i : boxes) {
                    const string &varname = i.first;
                    Box &box = i.second;
                    debug(dbg_prefetch) << "  var:" << varname << ":\n";
                    for (size_t k = 0; k < box.size(); k++) {
                        debug(dbg_prefetch) << "    ---\n";
                        debug(dbg_prefetch) << "    box[" << k << "].min: " << box[k].min << "\n";
                        debug(dbg_prefetch) << "    box[" << k << "].max: " << box[k].max << "\n";
                    }
                    debug(dbg_prefetch) << "    ---------\n";

#if 0 // todo create_buffer_t from box (see BoundsInference.cpp)
                    Expr prefetch_buf_t = Call::make(type_of<struct buffer_t *>(), Call::create_buffer_t,
                                                      output_buffer_t_args, Call::Intrinsic);
                    // Add prefetch to body on inputs
                    // Todo: For each input...
                    Expr tmp = Expr(0);
                    Stmt prefetch =
                        Evaluate::make(Call::make(Int(32), fetch_func,
                                          {tmp, prefetch_buf_t}, Call::Extern));
                    body = Block::make({prefetch, body});
#endif
                }

                scope.pop(op->name);
            }
        }

        body = mutate(body);
        stmt = For::make(op->name, op->min, op->extent, op->for_type, op->device_api, body);
    }

};

Stmt inject_prefetch(Stmt s, const std::map<std::string, Function> &env)
{
    if (char *dbg = getenv("HL_DBG_PREFETCH")) {
        dbg_prefetch  -= atoi(dbg);
        dbg_prefetch2 -= atoi(dbg);
        if (dbg_prefetch < 0) {
            dbg_prefetch = 0;
        }
        if (dbg_prefetch2 < 0) {
            dbg_prefetch2 = 0;
        }
    }
    return InjectPrefetch(env).mutate(s);
}

}
}
<commit_msg>Add codegen for create_buffer_t & halide_prefetch_buffer_t<commit_after>#include <algorithm>
#include <map>
#include <string>
#include <limits>

#include "Prefetch.h"
#include "CodeGen_Internal.h"
#include "IRMutator.h"
#include "IROperator.h"
#include "Bounds.h"
#include "Scope.h"
#include "Simplify.h"
#include "Substitute.h"
#include "Util.h"

namespace Halide {
namespace Internal {

using std::map;
using std::string;
using std::vector;
using std::stack;

// Prefetch debug levels
int dbg_prefetch  = 1;
int dbg_prefetch2 = 2;
int dbg_prefetch3 = 10;

class InjectPrefetch : public IRMutator {
public:
    InjectPrefetch(const map<string, Function> &e)
        : env(e) { }
private:
    const map<string, Function> &env;
    Scope<Interval> scope;
    unsigned long ptmp = 0;   // ID for all tmp vars in a prefetch op

private:
    using IRMutator::visit;

    // Strip down the tuple name, e.g. f.*.var into f
    string tuple_func(const string &name) {
        vector<string> v = split_string(name, ".");
        internal_assert(v.size() > 0);
        return v[0];
    }

    // Strip down the tuple name, e.g. f.*.var into var
    string tuple_var(const string &name) {
        vector<string> v = split_string(name, ".");
        internal_assert(v.size() > 0);
        return v[v.size()-1];
    }

    Function get_func(const string &name) {
        map<string, Function>::const_iterator iter = env.find(name);
        internal_assert(iter != env.end()) << "Realize node refers to function not in environment.\n";
        return iter->second;
    }

    void visit(const Let *op) {
        Interval in = bounds_of_expr_in_scope(op->value, scope);
        scope.push(op->name, in);
        IRMutator::visit(op);
        scope.pop(op->name);
    }
    void visit(const LetStmt *op) {
        Interval in = bounds_of_expr_in_scope(op->value, scope);
        scope.push(op->name, in);
        IRMutator::visit(op);
        scope.pop(op->name);
    }

    void visit(const For *op) {
        Stmt body = op->body;

        string func_name = tuple_func(op->name);
        string var_name  = tuple_var(op->name);
        vector<Prefetch> &prefetches = get_func(func_name).schedule().prefetches();

        if (prefetches.empty()) {
            debug(dbg_prefetch2) << "InjectPrefetch: " << op->name << " " << func_name << " " << var_name;
            debug(dbg_prefetch2) << " No prefetch\n";
        } else {
            debug(dbg_prefetch) << "InjectPrefetch: " << op->name << " " << func_name << " " << var_name;
            debug(dbg_prefetch) << " Found prefetch directive(s)\n";
        }

        for (const Prefetch &p : prefetches) {
            debug(dbg_prefetch) << "InjectPrefetch: check var:" << p.var
                               << " offset:" << p.offset << "\n";
            if (p.var == var_name) {
                debug(dbg_prefetch) << " prefetch on " << var_name << "\n";

                // Interval prein(op->name, op->name);
                // Add in prefetch offset
                Expr var = Variable::make(Int(32), op->name);
                Interval prein(var + p.offset, var + p.offset);
                scope.push(op->name, prein);

                map<string, Box> boxes;
                boxes = boxes_required(body, scope);

                debug(dbg_prefetch) << "  boxes required:\n";
                for (auto &b : boxes) {
                    const string &varname = b.first;
                    Box &box = b.second;
                    int dims = box.size();
                    debug(dbg_prefetch) << "  var:" << varname << ":\n";
                    for (int i = 0; i < dims; i++) {
                        debug(dbg_prefetch) << "    ---\n";
                        debug(dbg_prefetch) << "    box[" << i << "].min: " << box[i].min << "\n";
                        debug(dbg_prefetch) << "    box[" << i << "].max: " << box[i].max << "\n";
                    }
                    debug(dbg_prefetch) << "    ---------\n";

                    string pstr = std::to_string(ptmp++);
                    string varname_prefetch_buf = varname + ".prefetch_" + pstr + "_buf";
                    Expr var_prefetch_buf = Variable::make(Int(32), varname_prefetch_buf);

                    // Make the names for accessing the buffer strides
                    vector<Expr> stride_var(dims);
                    for (int i = 0; i < dims; i++) {
                        string istr = std::to_string(i);
                        string stride_name = varname + ".stride." + istr;
                        stride_var[i] = Variable::make(Int(32), stride_name);
                    }

                    // Make the names for the prefetch box mins & maxes
                    vector<string> min_name(dims), max_name(dims);
                    for (int i = 0; i < dims; i++) {
                        string istr = std::to_string(i);
                        min_name[i] = varname + ".prefetch_" + pstr + "_min_" + istr;
                        max_name[i] = varname + ".prefetch_" + pstr + "_max_" + istr;
                    }
                    vector<Expr> min_var(dims), max_var(dims);
                    for (int i = 0; i < dims; i++) {
                        min_var[i] = Variable::make(Int(32), min_name[i]);
                        max_var[i] = Variable::make(Int(32), max_name[i]);
                    }

                    // Create a buffer_t object for this prefetch.
                    Type t = Int(8);  // FIXME (need type of box...or extract elem_size)
                    vector<Expr> args(dims*3 + 2);
                    Expr first_elem = Load::make(t, varname, 0, Buffer(), Parameter());
                    args[0] = Call::make(Handle(), Call::address_of, {first_elem}, Call::PureIntrinsic);
                    args[1] = make_zero(t);
                    for (int i = 0; i < dims; i++) {
                        args[3*i+2] = min_var[i];
                        args[3*i+3] = max_var[i] - min_var[i] + 1;
                        args[3*i+4] = stride_var[i];
                    }

                    // Inject the prefetch call
                    string fetch_func = "halide_prefetch_buffer_t";
                    Stmt stmt_prefetch =
                        Evaluate::make(Call::make(Int(32), fetch_func,
                                          {dims, var_prefetch_buf}, Call::Extern));
                    body = Block::make({stmt_prefetch, body});

                    // Inject the create_buffer_t call
                    Expr prefetch_buf = Call::make(type_of<struct buffer_t *>(), Call::create_buffer_t,
                                          args, Call::Intrinsic);
                    body = LetStmt::make(varname_prefetch_buf, prefetch_buf, body);

                    // Inject bounds variable assignments
                    for (int i = dims-1; i >= 0; i--) {
                        body = LetStmt::make(max_name[i], box[i].max, body);
                        body = LetStmt::make(min_name[i], box[i].min, body);
                        // stride already defined by input buffer
                    }

                    debug(dbg_prefetch3) << "    prefetch body:\n";
                    debug(dbg_prefetch3) << body << "\n";
                }

                scope.pop(op->name);
            }
        }

        body = mutate(body);
        stmt = For::make(op->name, op->min, op->extent, op->for_type, op->device_api, body);
    }

};

Stmt inject_prefetch(Stmt s, const std::map<std::string, Function> &env)
{
    size_t read;
    std::string lvl = get_env_variable("HL_DEBUG_PREFETCH", read);
    if (read) {
        int dbg_level = atoi(lvl.c_str());
        dbg_prefetch  -= dbg_level;
        dbg_prefetch2 -= dbg_level;
        dbg_prefetch3 -= dbg_level;
        if (dbg_prefetch < 0) {
            dbg_prefetch = 0;
        }
        if (dbg_prefetch2 < 0) {
            dbg_prefetch2 = 0;
        }
        if (dbg_prefetch3 < 0) {
            dbg_prefetch3 = 0;
        }
    }
    return InjectPrefetch(env).mutate(s);
}

}
}
<|endoftext|>


<commit_before>/*
    This file is part of Akregator.

    Copyright (C) 2004 Stanislav Karchebny <Stanislav.Karchebny@kdemail.net>
                  2005 Frank Osterfeld <frank.osterfeld at kdemail.net>
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

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

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include "article.h"
#include "feed.h"
#include "feedstorage.h"
#include "storage.h"
#include "librss/librss.h"
#include "shared.h"
#include "utils.h"

#include <qdatetime.h>
#include <qdom.h>
#include <qregexp.h>
#include <qstringlist.h>
#include <qvaluelist.h>

#include <krfcdate.h>
#include <kdebug.h>
#include <kurl.h>

namespace Akregator {

struct Article::Private : public Shared
{
    /** The status of the article is stored in an int, the bits having the
        following meaning:

        0000 0001 Deleted
        0000 0010 Trash
        0000 0100 New
        0000 1000 Read
        0001 0000 Keep
     */

    enum Status {Deleted=0x01, Trash=0x02, New=0x04, Read=0x08, Keep=0x10};

    int status;
    QString guid;
    uint hash;
    Backend::FeedStorage* archive;
    QDateTime pubDate;
    Feed* feed;
};

Article::Article() : d(new Private)
{
    d->hash = 0;
    d->status = 0;
    d->feed = 0;
    d->archive = 0;
    d->pubDate.setTime_t(1);

}

Article::Article(const QString& guid, Feed* feed) : d(new Private)
{
    d->feed = feed;
    d->guid = guid;
    d->archive = Backend::Storage::getInstance()->archiveFor(feed->xmlUrl());
    d->status = d->archive->status(d->guid);
    d->pubDate.setTime_t(d->archive->pubDate(d->guid));
    d->hash = d->archive->hash(d->guid);
}

void Article::initialize(RSS::Article article, Backend::FeedStorage* archive)
{
    d->archive = archive;
    d->status = Private::New;
    d->hash = Utils::calcHash(article.title() + article.description() + article.link().url() + article.commentsLink().url() );

    d->guid = article.guid();

    if (!d->archive->contains(d->guid))
    {
        d->archive->addEntry(d->guid);

        if (article.meta("deleted") == "true")
        { // if article is in deleted state, we just add the status and omit the rest
            d->status = Private::Read | Private::Deleted;
            d->archive->setStatus(d->guid, d->status);
        }
        else
        { // article is not deleted, let's add it to the archive

            d->archive->setHash(d->guid, d->hash);
            QString title = article.title().isEmpty() ? buildTitle(article.description()) :  article.title();
            d->archive->setTitle(d->guid, title);
            d->archive->setDescription(d->guid, article.description());
            d->archive->setLink(d->guid, article.link().url());
            d->archive->setComments(d->guid, article.comments());
            d->archive->setCommentsLink(d->guid, article.commentsLink().url());
            d->archive->setGuidIsPermaLink(d->guid, article.guidIsPermaLink());
            d->archive->setGuidIsHash(d->guid, article.meta("guidIsHash") == "true");
            d->pubDate = article.pubDate().isValid() ? article.pubDate() : QDateTime::currentDateTime();
            d->archive->setPubDate(d->guid, d->pubDate.toTime_t());

            QValueList<RSS::Category> cats = article.categories();
            QValueList<RSS::Category>::ConstIterator end = cats.end();

            for (QValueList<RSS::Category>::ConstIterator it = cats.begin(); it != end; ++it)
            {
                Backend::Category cat;

                cat.term = (*it).category();
                cat.scheme = (*it).domain();
                cat.name = (*it).category();

                d->archive->addCategory(d->guid, cat);
            }

            if (!article.enclosure().isNull())
            {
                d->archive->setEnclosure(d->guid, article.enclosure().url(), article.enclosure().type(), article.enclosure().length());
            }
            else
            {
                d->archive->removeEnclosure(d->guid);
            }

            QString status = article.meta("status");

            if (!status.isEmpty())
            {
                int statusInt = status.toInt();
                if (statusInt == New)
                    statusInt = Unread;
                setStatus(statusInt);
            }
            setKeep(article.meta("keep") == "true");
        }
    }
    else
    {
        // always update comments count, as it's not used for hash calculation
        d->archive->setComments(d->guid, article.comments());
        if (d->hash != d->archive->hash(d->guid)) //article is in archive, was it modified?
        { // if yes, update
            d->pubDate.setTime_t(d->archive->pubDate(d->guid));
            d->archive->setHash(d->guid, d->hash);
            QString title = article.title().isEmpty() ? buildTitle(article.description()) :  article.title();
            d->archive->setTitle(d->guid, title);
            d->archive->setDescription(d->guid, article.description());
            d->archive->setLink(d->guid, article.link().url());
            d->archive->setCommentsLink(d->guid, article.commentsLink().url());
        }
    }
}

Article::Article(RSS::Article article, Feed* feed) : d(new Private)
{
    //assert(feed)
    d->feed = feed;
    initialize(article, Backend::Storage::getInstance()->archiveFor(feed->xmlUrl()));
}

Article::Article(RSS::Article article, Backend::FeedStorage* archive) : d(new Private)
{
    d->feed = 0;
    initialize(article, archive);
}

bool Article::isNull() const
{
    return d->archive == 0; // TODO: use proper null state
}

void Article::offsetPubDate(int secs)
{
   d->pubDate = d->pubDate.addSecs(secs);
   d->archive->setPubDate(d->guid, d->pubDate.toTime_t());

}

void Article::setDeleted()
{
    if (isDeleted())
        return;

    setStatus(Read);
    d->status = Private::Deleted | Private::Read;
    d->archive->setStatus(d->guid, d->status);
    d->archive->setDeleted(d->guid);

    if (d->feed)
        d->feed->setArticleDeleted(*this);
}

bool Article::isDeleted() const
{
    return (d->status & Private::Deleted) != 0;
}

Article::Article(const Article &other) : d(new Private)
{
    *this = other;
}

Article::~Article()
{
    if (d->deref())
    {
        delete d;
        d = 0;
    }
}

Article &Article::operator=(const Article &other)
{
    if (this != &other) {
        other.d->ref();
        if (d && d->deref())
            delete d;
        d = other.d;
    }
    return *this;
}

bool Article::operator<(const Article &other) const
{
    return pubDate() > other.pubDate();
}

bool Article::operator<=(const Article &other) const
{
    return pubDate() >= other.pubDate();
}

bool Article::operator>(const Article &other) const
{
    return pubDate() < other.pubDate();
}

bool Article::operator>=(const Article &other) const
{
    return pubDate() <= other.pubDate();
}

bool Article::operator==(const Article &other) const
{
    return d->guid == other.guid();
}

int Article::status() const
{
    if ((d->status & Private::Read) != 0)
        return Read;

    if ((d->status & Private::New) != 0)
        return New;
    else
        return Unread;
}

void Article::setStatus(int stat)
{
    int oldStatus = status();

    if (oldStatus != stat)
    {
        switch (stat)
        {
            case Read:
                d->status = (d->status | Private::Read) & ~Private::New;
                break;
            case Unread:
                d->status = (d->status & ~Private::Read) & ~Private::New;
                break;
            case New:
                d->status = (d->status | Private::New) & ~Private::Read;
                break;
        }
        d->archive->setStatus(d->guid, d->status);
        if (d->feed)
            d->feed->setArticleChanged(*this, oldStatus);
     }
}

QString Article::title() const
{
    return d->archive->title(d->guid);
}

KURL Article::link() const
{
    return d->archive->link(d->guid);
}

QString Article::description() const
{
    return d->archive->description(d->guid);
}

QString Article::guid() const
{
    return d->guid;
}

KURL Article::commentsLink() const
{
    return d->archive->commentsLink(d->guid);
}

int Article::comments() const
{

    return d->archive->comments(d->guid);
}

bool Article::guidIsPermaLink() const
{
    return d->archive->guidIsPermaLink(d->guid);
}

bool Article::guidIsHash() const
{
    return d->archive->guidIsHash(d->guid);
}

uint Article::hash() const
{
    return d->hash;
}

bool Article::keep() const
{
    return (d->status & Private::Keep) != 0;
}

RSS::Enclosure Article::enclosure() const
{
    bool hasEnc;
    QString url, type;
    int length;
    d->archive->enclosure(d->guid, hasEnc, url, type, length);
    return hasEnc ? RSS::Enclosure(url, length, type) : RSS::Enclosure();

}

void Article::setKeep(bool keep)
{
    d->status = keep ? (d->status | Private::Keep) : (d->status & ~Private::Keep);
    d->archive->setStatus(d->guid, d->status);
    if (d->feed)
        d->feed->setArticleChanged(*this);
}

void Article::addTag(const QString& tag)
{
    d->archive->addTag(d->guid, tag);
    if (d->feed)
        d->feed->setArticleChanged(*this);
}

void Article::removeTag(const QString& tag)
{
    d->archive->removeTag(d->guid, tag);
    if (d->feed)
        d->feed->setArticleChanged(*this);
}

bool Article::hasTag(const QString& tag) const
{
    return d->archive->tags(d->guid).contains(tag);
}

QStringList Article::tags() const
{
    return d->archive->tags(d->guid);
}

Feed* Article::feed() const
{ return d->feed; }

const QDateTime& Article::pubDate() const
{
    return d->pubDate;
}

QString Article::buildTitle(const QString& description)
{
    QString s = description;
    if (description.stripWhiteSpace().isEmpty())
        return "";

    int i = s.find('>',500); /*avoid processing too much */
    if (i != -1)
        s = s.left(i+1);
    QRegExp rx("(<([^\\s>]*)(?:[^>]*)>)[^<]*", false);
    QString tagName, toReplace, replaceWith;
    while (rx.search(s) != -1 )
    {
        tagName=rx.cap(2);
        if (tagName=="SCRIPT"||tagName=="script")
            toReplace=rx.cap(0); // strip tag AND tag contents
        else if (tagName.startsWith("br") || tagName.startsWith("BR"))
        {
            toReplace=rx.cap(1);
            replaceWith=" ";
        }
        else
            toReplace=rx.cap(1);  // strip just tag
        s=s.replace(s.find(toReplace),toReplace.length(),replaceWith); // do the deed
    }
    if (s.length()> 90)
        s=s.left(90)+"...";
    return s.simplifyWhiteSpace();
}
} // namespace Akregator
<commit_msg>Fix comparison operators of Article, such as < and <=. This fixes problems with QMap and articles having identical pubdate (operator< just compared pubdates, and QMap consideres  articles as equal when items are not comparable). Fixes 114997 navigation problems and prevents creation of a new item when selecting an unread dupe article. (a new item was  created as map lookup failed).<commit_after>/*
    This file is part of Akregator.

    Copyright (C) 2004 Stanislav Karchebny <Stanislav.Karchebny@kdemail.net>
                  2005 Frank Osterfeld <frank.osterfeld at kdemail.net>
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

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

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include "article.h"
#include "feed.h"
#include "feedstorage.h"
#include "storage.h"
#include "librss/librss.h"
#include "shared.h"
#include "utils.h"

#include <qdatetime.h>
#include <qdom.h>
#include <qregexp.h>
#include <qstringlist.h>
#include <qvaluelist.h>

#include <krfcdate.h>
#include <kdebug.h>
#include <kurl.h>

namespace Akregator {

struct Article::Private : public Shared
{
    /** The status of the article is stored in an int, the bits having the
        following meaning:

        0000 0001 Deleted
        0000 0010 Trash
        0000 0100 New
        0000 1000 Read
        0001 0000 Keep
     */

    enum Status {Deleted=0x01, Trash=0x02, New=0x04, Read=0x08, Keep=0x10};

    int status;
    QString guid;
    uint hash;
    Backend::FeedStorage* archive;
    QDateTime pubDate;
    Feed* feed;
};

Article::Article() : d(new Private)
{
    d->hash = 0;
    d->status = 0;
    d->feed = 0;
    d->archive = 0;
    d->pubDate.setTime_t(1);

}

Article::Article(const QString& guid, Feed* feed) : d(new Private)
{
    d->feed = feed;
    d->guid = guid;
    d->archive = Backend::Storage::getInstance()->archiveFor(feed->xmlUrl());
    d->status = d->archive->status(d->guid);
    d->pubDate.setTime_t(d->archive->pubDate(d->guid));
    d->hash = d->archive->hash(d->guid);
}

void Article::initialize(RSS::Article article, Backend::FeedStorage* archive)
{
    d->archive = archive;
    d->status = Private::New;
    d->hash = Utils::calcHash(article.title() + article.description() + article.link().url() + article.commentsLink().url() );

    d->guid = article.guid();

    if (!d->archive->contains(d->guid))
    {
        d->archive->addEntry(d->guid);

        if (article.meta("deleted") == "true")
        { // if article is in deleted state, we just add the status and omit the rest
            d->status = Private::Read | Private::Deleted;
            d->archive->setStatus(d->guid, d->status);
        }
        else
        { // article is not deleted, let's add it to the archive

            d->archive->setHash(d->guid, d->hash);
            QString title = article.title().isEmpty() ? buildTitle(article.description()) :  article.title();
            d->archive->setTitle(d->guid, title);
            d->archive->setDescription(d->guid, article.description());
            d->archive->setLink(d->guid, article.link().url());
            d->archive->setComments(d->guid, article.comments());
            d->archive->setCommentsLink(d->guid, article.commentsLink().url());
            d->archive->setGuidIsPermaLink(d->guid, article.guidIsPermaLink());
            d->archive->setGuidIsHash(d->guid, article.meta("guidIsHash") == "true");
            d->pubDate = article.pubDate().isValid() ? article.pubDate() : QDateTime::currentDateTime();
            d->archive->setPubDate(d->guid, d->pubDate.toTime_t());

            QValueList<RSS::Category> cats = article.categories();
            QValueList<RSS::Category>::ConstIterator end = cats.end();

            for (QValueList<RSS::Category>::ConstIterator it = cats.begin(); it != end; ++it)
            {
                Backend::Category cat;

                cat.term = (*it).category();
                cat.scheme = (*it).domain();
                cat.name = (*it).category();

                d->archive->addCategory(d->guid, cat);
            }

            if (!article.enclosure().isNull())
            {
                d->archive->setEnclosure(d->guid, article.enclosure().url(), article.enclosure().type(), article.enclosure().length());
            }
            else
            {
                d->archive->removeEnclosure(d->guid);
            }

            QString status = article.meta("status");

            if (!status.isEmpty())
            {
                int statusInt = status.toInt();
                if (statusInt == New)
                    statusInt = Unread;
                setStatus(statusInt);
            }
            setKeep(article.meta("keep") == "true");
        }
    }
    else
    {
        // always update comments count, as it's not used for hash calculation
        d->archive->setComments(d->guid, article.comments());
        if (d->hash != d->archive->hash(d->guid)) //article is in archive, was it modified?
        { // if yes, update
            d->pubDate.setTime_t(d->archive->pubDate(d->guid));
            d->archive->setHash(d->guid, d->hash);
            QString title = article.title().isEmpty() ? buildTitle(article.description()) :  article.title();
            d->archive->setTitle(d->guid, title);
            d->archive->setDescription(d->guid, article.description());
            d->archive->setLink(d->guid, article.link().url());
            d->archive->setCommentsLink(d->guid, article.commentsLink().url());
        }
    }
}

Article::Article(RSS::Article article, Feed* feed) : d(new Private)
{
    //assert(feed)
    d->feed = feed;
    initialize(article, Backend::Storage::getInstance()->archiveFor(feed->xmlUrl()));
}

Article::Article(RSS::Article article, Backend::FeedStorage* archive) : d(new Private)
{
    d->feed = 0;
    initialize(article, archive);
}

bool Article::isNull() const
{
    return d->archive == 0; // TODO: use proper null state
}

void Article::offsetPubDate(int secs)
{
   d->pubDate = d->pubDate.addSecs(secs);
   d->archive->setPubDate(d->guid, d->pubDate.toTime_t());

}

void Article::setDeleted()
{
    if (isDeleted())
        return;

    setStatus(Read);
    d->status = Private::Deleted | Private::Read;
    d->archive->setStatus(d->guid, d->status);
    d->archive->setDeleted(d->guid);

    if (d->feed)
        d->feed->setArticleDeleted(*this);
}

bool Article::isDeleted() const
{
    return (d->status & Private::Deleted) != 0;
}

Article::Article(const Article &other) : d(new Private)
{
    *this = other;
}

Article::~Article()
{
    if (d->deref())
    {
        delete d;
        d = 0;
    }
}

Article &Article::operator=(const Article &other)
{
    if (this != &other) {
        other.d->ref();
        if (d && d->deref())
            delete d;
        d = other.d;
    }
    return *this;
}

bool Article::operator<(const Article &other) const
{
    return pubDate() > other.pubDate() ||
            (pubDate() == other.pubDate() && guid() < other.guid() );
}

bool Article::operator<=(const Article &other) const
{
    return (pubDate() > other.pubDate() || *this == other);
}

bool Article::operator>(const Article &other) const
{
    return pubDate() < other.pubDate() ||
            (pubDate() == other.pubDate() && guid() > other.guid() );
}

bool Article::operator>=(const Article &other) const
{
    return (pubDate() > other.pubDate() || *this == other);
}

bool Article::operator==(const Article &other) const
{
    return d->guid == other.guid();
}

int Article::status() const
{
    if ((d->status & Private::Read) != 0)
        return Read;

    if ((d->status & Private::New) != 0)
        return New;
    else
        return Unread;
}

void Article::setStatus(int stat)
{
    int oldStatus = status();

    if (oldStatus != stat)
    {
        switch (stat)
        {
            case Read:
                d->status = (d->status | Private::Read) & ~Private::New;
                break;
            case Unread:
                d->status = (d->status & ~Private::Read) & ~Private::New;
                break;
            case New:
                d->status = (d->status | Private::New) & ~Private::Read;
                break;
        }
        d->archive->setStatus(d->guid, d->status);
        if (d->feed)
            d->feed->setArticleChanged(*this, oldStatus);
     }
}

QString Article::title() const
{
    return d->archive->title(d->guid);
}

KURL Article::link() const
{
    return d->archive->link(d->guid);
}

QString Article::description() const
{
    return d->archive->description(d->guid);
}

QString Article::guid() const
{
    return d->guid;
}

KURL Article::commentsLink() const
{
    return d->archive->commentsLink(d->guid);
}

int Article::comments() const
{

    return d->archive->comments(d->guid);
}

bool Article::guidIsPermaLink() const
{
    return d->archive->guidIsPermaLink(d->guid);
}

bool Article::guidIsHash() const
{
    return d->archive->guidIsHash(d->guid);
}

uint Article::hash() const
{
    return d->hash;
}

bool Article::keep() const
{
    return (d->status & Private::Keep) != 0;
}

RSS::Enclosure Article::enclosure() const
{
    bool hasEnc;
    QString url, type;
    int length;
    d->archive->enclosure(d->guid, hasEnc, url, type, length);
    return hasEnc ? RSS::Enclosure(url, length, type) : RSS::Enclosure();

}

void Article::setKeep(bool keep)
{
    d->status = keep ? (d->status | Private::Keep) : (d->status & ~Private::Keep);
    d->archive->setStatus(d->guid, d->status);
    if (d->feed)
        d->feed->setArticleChanged(*this);
}

void Article::addTag(const QString& tag)
{
    d->archive->addTag(d->guid, tag);
    if (d->feed)
        d->feed->setArticleChanged(*this);
}

void Article::removeTag(const QString& tag)
{
    d->archive->removeTag(d->guid, tag);
    if (d->feed)
        d->feed->setArticleChanged(*this);
}

bool Article::hasTag(const QString& tag) const
{
    return d->archive->tags(d->guid).contains(tag);
}

QStringList Article::tags() const
{
    return d->archive->tags(d->guid);
}

Feed* Article::feed() const
{ return d->feed; }

const QDateTime& Article::pubDate() const
{
    return d->pubDate;
}

QString Article::buildTitle(const QString& description)
{
    QString s = description;
    if (description.stripWhiteSpace().isEmpty())
        return "";

    int i = s.find('>',500); /*avoid processing too much */
    if (i != -1)
        s = s.left(i+1);
    QRegExp rx("(<([^\\s>]*)(?:[^>]*)>)[^<]*", false);
    QString tagName, toReplace, replaceWith;
    while (rx.search(s) != -1 )
    {
        tagName=rx.cap(2);
        if (tagName=="SCRIPT"||tagName=="script")
            toReplace=rx.cap(0); // strip tag AND tag contents
        else if (tagName.startsWith("br") || tagName.startsWith("BR"))
        {
            toReplace=rx.cap(1);
            replaceWith=" ";
        }
        else
            toReplace=rx.cap(1);  // strip just tag
        s=s.replace(s.find(toReplace),toReplace.length(),replaceWith); // do the deed
    }
    if (s.length()> 90)
        s=s.left(90)+"...";
    return s.simplifyWhiteSpace();
}
} // namespace Akregator
<|endoftext|>