text:
#pragma once

#include <platform/CHIPDeviceConfig.h>
#include <platform/CommissionableDataProvider.h>

#include "app/clusters/ota-requestor/OTARequestorInterface.h"
#include "app/server/CommissioningWindowManager.h"
#include "app/server/OnboardingCodesUtil.h"
#include "app/server/Server.h"
#include "credentials/FabricTable.h"
#include "device_service/device_service.rpc.pb.h"
#include "platform/CommissionableDataProvider.h"
#include "platform/ConfigurationManager.h"
#include "platform/DiagnosticDataProvider.h"
#include "platform/PlatformManager.h"
#include <platform/DeviceInstanceInfoProvider.h>
#include <setup_payload/QRCodeSetupPayloadGenerator.h>

namespace chip {
namespace rpc {

namespace Internal {
// This class supports changing the commissionable data provider values at
// runtime using the RPCs.
// This class is LazyInit after getting or setting any of it's values. After
// this the class wraps the original CommissionableDataProvider, returning the
// original values for anything which has not been overwritten.
//
// NOTE: Values written do not persist across a reboot.
class CommissionableDataProviderRpcWrapper : public DeviceLayer::CommissionableDataProvider
{
public:
    CHIP_ERROR GetSetupPasscode(uint32_t & setupPasscode) override
    {
        LazyInit();
        if (mPasscodeOverride.has_value())
        {
            setupPasscode = mPasscodeOverride.value();
            return CHIP_NO_ERROR;
        }
        if (mCommissionableDataProvider)
        {
            return mCommissionableDataProvider->GetSetupPasscode(setupPasscode);
        }
        return CHIP_ERROR_INTERNAL;
    }

    // NOTE: Changing the passcode will not change the verifier or anything else
    // this just changes the value returned from GetSetupPasscode.
    // Using this is completely optional, and only really useful for test
    // automation which can read the configured passcode for commissioning
    // after it is changed.
    CHIP_ERROR SetSetupPasscode(uint32_t setupPasscode) override
    {
        LazyInit();
        mPasscodeOverride = setupPasscode;
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override
    {
        LazyInit();
        if (mDiscriminatorOverride.has_value())
        {
            setupDiscriminator = mDiscriminatorOverride.value();
            return CHIP_NO_ERROR;
        }
        if (mCommissionableDataProvider)
        {
            return mCommissionableDataProvider->GetSetupDiscriminator(setupDiscriminator);
        }
        return CHIP_ERROR_INTERNAL;
    }

    CHIP_ERROR SetSetupDiscriminator(uint16_t setupDiscriminator) override
    {
        LazyInit();
        mDiscriminatorOverride = setupDiscriminator;
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override
    {
        LazyInit();
        if (mIterationCountOverride.has_value())
        {
            iterationCount = mIterationCountOverride.value();
            return CHIP_NO_ERROR;
        }
        if (mCommissionableDataProvider)
        {
            return mCommissionableDataProvider->GetSpake2pIterationCount(iterationCount);
        }
        return CHIP_ERROR_INTERNAL;
    }

    CHIP_ERROR SetSpake2pIterationCount(uint32_t iterationCount)
    {
        LazyInit();
        mIterationCountOverride = iterationCount;
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR GetSpake2pSalt(MutableByteSpan & saltBuf) override
    {
        LazyInit();
        if (mSaltOverride.has_value())
        {
            if (mSaltOverride.value().size() > saltBuf.size())
            {
                return CHIP_ERROR_BUFFER_TOO_SMALL;
            }
            std::copy(mSaltOverride.value().begin(), mSaltOverride.value().end(), saltBuf.begin());
            saltBuf.reduce_size(mSaltOverride.value().size());
            return CHIP_NO_ERROR;
        }
        if (mCommissionableDataProvider)
        {
            return mCommissionableDataProvider->GetSpake2pSalt(saltBuf);
        }
        return CHIP_ERROR_INTERNAL;
    }

    CHIP_ERROR SetSpake2pSalt(ByteSpan saltBuf)
    {
        LazyInit();
        if (sizeof(mSaltBuf) < saltBuf.size())
        {
            return CHIP_ERROR_BUFFER_TOO_SMALL;
        }
        std::copy(saltBuf.begin(), saltBuf.end(), mSaltBuf);
        mSaltOverride = ByteSpan(mSaltBuf, saltBuf.size());
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & outVerifierLen) override
    {
        LazyInit();
        if (mVerifierOverride.has_value())
        {
            outVerifierLen = mVerifierOverride.value().size();
            if (mVerifierOverride.value().size() > verifierBuf.size())
            {
                return CHIP_ERROR_BUFFER_TOO_SMALL;
            }
            std::copy(mVerifierOverride.value().begin(), mVerifierOverride.value().end(), verifierBuf.begin());
            verifierBuf.reduce_size(mVerifierOverride.value().size());
            return CHIP_NO_ERROR;
        }
        if (mCommissionableDataProvider)
        {
            return mCommissionableDataProvider->GetSpake2pVerifier(verifierBuf, outVerifierLen);
        }

        return CHIP_ERROR_INTERNAL;
    }

    CHIP_ERROR SetSpake2pVerifier(ByteSpan verifierBuf)
    {
        LazyInit();
        if (sizeof(mVerifierBuf) < verifierBuf.size())
        {
            return CHIP_ERROR_BUFFER_TOO_SMALL;
        }
        std::copy(verifierBuf.begin(), verifierBuf.end(), mVerifierBuf);
        mVerifierOverride = ByteSpan(mVerifierBuf, verifierBuf.size());
        return CHIP_NO_ERROR;
    }

private:
    std::optional<uint16_t> mDiscriminatorOverride;
    std::optional<uint32_t> mPasscodeOverride;
    Spake2pVerifierSerialized mVerifierBuf;
    std::optional<ByteSpan> mVerifierOverride;
    uint8_t mSaltBuf[kSpake2p_Max_PBKDF_Salt_Length];
    std::optional<ByteSpan> mSaltOverride;
    std::optional<uint32_t> mIterationCountOverride;
    DeviceLayer::CommissionableDataProvider * mCommissionableDataProvider = nullptr;

    void LazyInit()
    {
        if (!mCommissionableDataProvider)
        {
            mCommissionableDataProvider = DeviceLayer::GetCommissionableDataProvider();
            DeviceLayer::SetCommissionableDataProvider(this);
        }
    }
};
} // namespace Internal

class Device : public pw_rpc::nanopb::Device::Service<Device>
{
public:
    virtual ~Device() = default;

    virtual pw::Status FactoryReset(const pw_protobuf_Empty & request, pw_protobuf_Empty & response)
    {
        DeviceLayer::ConfigurationMgr().InitiateFactoryReset();
        return pw::OkStatus();
    }

    virtual pw::Status Reboot(const pw_protobuf_Empty & request, pw_protobuf_Empty & response)
    {
        return pw::Status::Unimplemented();
    }

    virtual pw::Status TriggerOta(const pw_protobuf_Empty & request, pw_protobuf_Empty & response)
    {
#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
        chip::DeviceLayer::PlatformMgr().ScheduleWork(
            [](intptr_t) {
                chip::OTARequestorInterface * requestor = chip::GetRequestorInstance();
                if (requestor == nullptr)
                {
                    ChipLogError(SoftwareUpdate, "Can't get the CASESessionManager");
                }
                else
                {
                    requestor->TriggerImmediateQuery();
                }
            },
            reinterpret_cast<intptr_t>(nullptr));
        return pw::OkStatus();
#else  // CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
        ChipLogError(AppServer, "Trigger OTA requested, but OTA requestor not compiled in.");
        return pw::Status::Unimplemented();
#endif // CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
    }

    virtual pw::Status SetOtaMetadataForProvider(const chip_rpc_MetadataForProvider & request, pw_protobuf_Empty & response)
    {
#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
        chip::OTARequestorInterface * requestor = chip::GetRequestorInstance();
        if (requestor == nullptr)
        {
            ChipLogError(SoftwareUpdate, "Can't get the CASESessionManager");
            return pw::Status::Unavailable();
        }
        else if (sizeof(metadataForProviderBuffer) < request.tlv.size)
        {
            return pw::Status::ResourceExhausted();
        }
        memcpy(metadataForProviderBuffer, request.tlv.bytes, request.tlv.size);
        DeviceLayer::StackLock lock;
        requestor->SetMetadataForProvider(chip::ByteSpan(metadataForProviderBuffer, request.tlv.size));
        return pw::OkStatus();
#else  // CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
        ChipLogError(AppServer, "OTA set metadata for provider requested, but OTA requestor not compiled in.");
        return pw::Status::Unimplemented();
#endif // CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
    }

    virtual pw::Status SetPairingState(const chip_rpc_PairingState & request, pw_protobuf_Empty & response)
    {
        if (request.pairing_enabled && !chip::Server::GetInstance().GetCommissioningWindowManager().IsCommissioningWindowOpen())
        {
            DeviceLayer::StackLock lock;
            chip::ChipError err = chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow();
            if (err != CHIP_NO_ERROR)
            {
                ChipLogError(NotSpecified, "RPC SetPairingState failed to open commissioning window: %" CHIP_ERROR_FORMAT,
                             err.Format());
                return pw::Status::Internal();
            }
        }
        else if (!request.pairing_enabled &&
                 chip::Server::GetInstance().GetCommissioningWindowManager().IsCommissioningWindowOpen())
        {
            DeviceLayer::StackLock lock;
            chip::Server::GetInstance().GetCommissioningWindowManager().CloseCommissioningWindow();
        }
        return pw::OkStatus();
    }

    virtual pw::Status GetPairingState(const pw_protobuf_Empty & request, chip_rpc_PairingState & response)
    {
        response.pairing_enabled = DeviceLayer::ConnectivityMgr().IsBLEAdvertisingEnabled();
        return pw::OkStatus();
    }

    virtual pw::Status GetDeviceState(const pw_protobuf_Empty & request, chip_rpc_DeviceState & response)
    {
        uint64_t time_since_boot_sec;
        DeviceLayer::GetDiagnosticDataProvider().GetUpTime(time_since_boot_sec);
        response.time_since_boot_millis = time_since_boot_sec * 1000;
        size_t count                    = 0;
        DeviceLayer::StackLock lock;
        for (const FabricInfo & fabricInfo : Server::GetInstance().GetFabricTable())
        {
            if (count < ArraySize(response.fabric_info))
            {
                response.fabric_info[count].fabric_id = fabricInfo.GetFabricId();
                response.fabric_info[count].node_id   = fabricInfo.GetPeerId().GetNodeId();
                count++;
            }
        }
        response.fabric_info_count = count;
        return pw::OkStatus();
    }

    virtual pw::Status GetDeviceInfo(const pw_protobuf_Empty & request, chip_rpc_DeviceInfo & response)
    {

        uint16_t vendor_id;
        if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetVendorId(vendor_id) == CHIP_NO_ERROR)
        {
            response.vendor_id = static_cast<uint32_t>(vendor_id);
        }
        else
        {
            return pw::Status::Internal();
        }

        uint16_t product_id;
        if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetProductId(product_id) == CHIP_NO_ERROR)
        {
            response.product_id = static_cast<uint32_t>(product_id);
        }
        else
        {
            return pw::Status::Internal();
        }

        uint32_t software_version;
        if (DeviceLayer::ConfigurationMgr().GetSoftwareVersion(software_version) == CHIP_NO_ERROR)
        {
            response.software_version = software_version;
        }
        else
        {
            return pw::Status::Internal();
        }

        if (DeviceLayer::ConfigurationMgr().GetSoftwareVersionString(response.software_version_string,
                                                                     sizeof(response.software_version_string)) != CHIP_NO_ERROR)
        {
            return pw::Status::Internal();
        }

        uint32_t code;
        if (DeviceLayer::GetCommissionableDataProvider()->GetSetupPasscode(code) == CHIP_NO_ERROR)
        {
            response.pairing_info.code = code;
            response.has_pairing_info  = true;
        }

        uint16_t discriminator;
        if (DeviceLayer::GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator) == CHIP_NO_ERROR)
        {
            response.pairing_info.discriminator = static_cast<uint32_t>(discriminator);
            response.has_pairing_info           = true;
        }

        if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetSerialNumber(response.serial_number, sizeof(response.serial_number)) !=
            CHIP_NO_ERROR)
        {
            return pw::Status::Internal();
        }

        // Create buffer for QR code that can fit max size and null terminator.
        char qrCodeBuffer[chip::QRCodeBasicSetupPayloadGenerator::kMaxQRCodeBase38RepresentationLength + 1];
        chip::MutableCharSpan qrCodeText(qrCodeBuffer);
        if (GetQRCode(qrCodeText, chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)) == CHIP_NO_ERROR)
        {
            snprintf(response.pairing_info.qr_code, sizeof(response.pairing_info.qr_code), "%s", qrCodeText.data());
            GetQRCodeUrl(response.pairing_info.qr_code_url, sizeof(response.pairing_info.qr_code_url), qrCodeText);
            response.has_pairing_info = true;
        }

        return pw::OkStatus();
    }

    virtual pw::Status GetSpakeInfo(const pw_protobuf_Empty & request, chip_rpc_SpakeInfo & response)
    {
        size_t serializedVerifierLen = 0;
        MutableByteSpan verifierSpan{ response.verifier.bytes };
        if (DeviceLayer::GetCommissionableDataProvider()->GetSpake2pVerifier(verifierSpan, serializedVerifierLen) == CHIP_NO_ERROR)
        {
            response.verifier.size = verifierSpan.size();
            response.has_verifier  = true;
        }

        MutableByteSpan saltSpan{ response.salt.bytes };
        if (DeviceLayer::GetCommissionableDataProvider()->GetSpake2pSalt(saltSpan) == CHIP_NO_ERROR)
        {
            response.salt.size = saltSpan.size();
            response.has_salt  = true;
        }

        if (DeviceLayer::GetCommissionableDataProvider()->GetSpake2pIterationCount(response.iteration_count) == CHIP_NO_ERROR)
        {
            response.has_iteration_count = true;
        }

        return pw::OkStatus();
    }

    virtual pw::Status SetSpakeInfo(const chip_rpc_SpakeInfo & request, pw_protobuf_Empty & response)
    {
        if (request.has_salt)
        {
            mCommissionableDataProvider.SetSpake2pSalt(ByteSpan(request.salt.bytes, request.salt.size));
        }
        if (request.has_iteration_count)
        {
            mCommissionableDataProvider.SetSpake2pIterationCount(request.iteration_count);
        }
        if (request.has_verifier)
        {
            mCommissionableDataProvider.SetSpake2pVerifier(ByteSpan(request.verifier.bytes, request.verifier.size));
        }

        if (Server::GetInstance().GetCommissioningWindowManager().IsCommissioningWindowOpen() &&
            Server::GetInstance().GetCommissioningWindowManager().CommissioningWindowStatusForCluster() !=
                app::Clusters::AdministratorCommissioning::CommissioningWindowStatus::kEnhancedWindowOpen)
        {
            // Cache values before closing to restore them after restart.
            app::DataModel::Nullable<VendorId> vendorId = Server::GetInstance().GetCommissioningWindowManager().GetOpenerVendorId();
            app::DataModel::Nullable<FabricIndex> fabricIndex =
                Server::GetInstance().GetCommissioningWindowManager().GetOpenerFabricIndex();

            // Restart commissioning window to recache the spakeInfo values:
            {
                DeviceLayer::StackLock lock;
                Server::GetInstance().GetCommissioningWindowManager().CloseCommissioningWindow();
            }
            // Let other tasks possibly work since Commissioning window close/open are "heavy"
            if (Server::GetInstance().GetCommissioningWindowManager().CommissioningWindowStatusForCluster() !=
                    app::Clusters::AdministratorCommissioning::CommissioningWindowStatus::kWindowNotOpen &&
                !vendorId.IsNull() && !fabricIndex.IsNull())
            {
                DeviceLayer::StackLock lock;
                System::Clock::Seconds16 commissioningTimeout =
                    System::Clock::Seconds16(CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS); // Use default for timeout for now.
                Server::GetInstance()
                    .GetCommissioningWindowManager()
                    .OpenBasicCommissioningWindowForAdministratorCommissioningCluster(commissioningTimeout, fabricIndex.Value(),
                                                                                vendorId.Value());
            }
            else
            {
                DeviceLayer::StackLock lock;
                Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow();
            }
        }

        return pw::OkStatus();
    }

    // NOTE: Changing the passcode will not change the verifier or anything else
    // this just changes the value returned from GetSetupPasscode.
    // Using this is completely optional, and only really useful for test
    // automation which can read the configured passcode for commissioning
    // after it is changed.
    virtual pw::Status SetPairingInfo(const chip_rpc_PairingInfo & request, pw_protobuf_Empty & response)
    {
        if (mCommissionableDataProvider.SetSetupPasscode(request.code) != CHIP_NO_ERROR ||
            mCommissionableDataProvider.SetSetupDiscriminator(request.discriminator) != CHIP_NO_ERROR)
        {
            return pw::Status::Unknown();
        }
        return pw::OkStatus();
    }

private:
#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
    static constexpr size_t kMaxMetadataForProviderLength = 512; // length defined in chip spec 11.20.6.7
    uint8_t metadataForProviderBuffer[kMaxMetadataForProviderLength];
#endif // CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
    Internal::CommissionableDataProviderRpcWrapper mCommissionableDataProvider;
};

} // namespace rpc
} // namespace chip


text:
layout: post
date:	2009-01-25 13:37:00
title:  How does it happen?
tags: [archived-posts]
categories: archives
permalink: /:categories/:year/:month/:day/:title/
---
Watched "Slumdog Millionaire"...and got to wondering, "how is it that I am born so privileged, and others are not?"

After years of pondering this, I have no answer....I can only thank my good luck.

Meanwhile, here's a TICKELL'S BLUE FLYCATCHER singing sweetly at the Valley School this morning (yes, I went *again*!)

Do remember, if you are in India, to watch the Republic Day Parade floats on TV! They make a great spectacle.

redpajama_set_name: RedPajamaGithub


text:
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)

using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;
using System.Windows;

using ICSharpCode.AvalonEdit.Document;

namespace ICSharpCode.AvalonEdit.Highlighting
{
	///
	/// Allows copying HTML text to the clipboard.
	///
	public static class HtmlClipboard
	{
		///
		/// Builds a header for the CF_HTML clipboard format.
		///
		static string BuildHeader(int startHTML, int endHTML, int startFragment, int endFragment)
		{
			StringBuilder b = new StringBuilder();
			b.AppendLine("Version:0.9");
			b.AppendLine("StartHTML:" + startHTML.ToString("d8", CultureInfo.InvariantCulture));
			b.AppendLine("EndHTML:" + endHTML.ToString("d8", CultureInfo.InvariantCulture));
			b.AppendLine("StartFragment:" + startFragment.ToString("d8", CultureInfo.InvariantCulture));
			b.AppendLine("EndFragment:" + endFragment.ToString("d8", CultureInfo.InvariantCulture));
			return b.ToString();
		}

		///
		/// Sets the TextDataFormat.Html on the data object to the specified html fragment.
		/// This helper methods takes care of creating the necessary CF_HTML header.
		///
		public static void SetHtml(DataObject dataObject, string htmlFragment)
		{
			if (dataObject == null)
				throw new ArgumentNullException("dataObject");
			if (htmlFragment == null)
				throw new ArgumentNullException("htmlFragment");

			string htmlStart = @"<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.0 Transitional//EN"">" + Environment.NewLine
				+ "" + Environment.NewLine
				+ "" + Environment.NewLine
				+ "" + Environment.NewLine;
			string htmlEnd = "" + Environment.NewLine + "" + Environment.NewLine + "" + Environment.NewLine;
			string dummyHeader = BuildHeader(0, 0, 0, 0);
			// the offsets are stored as UTF-8 bytes (see CF_HTML documentation)
			int startHTML = dummyHeader.Length;
			int startFragment = startHTML + htmlStart.Length;
			int endFragment = startFragment + Encoding.UTF8.GetByteCount(htmlFragment);
			int endHTML = endFragment + htmlEnd.Length;
			string cf_html = BuildHeader(startHTML, endHTML, startFragment, endFragment) + htmlStart + htmlFragment + htmlEnd;
			Debug.WriteLine(cf_html);
			dataObject.SetText(cf_html, TextDataFormat.Html);
		}

		///
		/// Creates a HTML fragment from a part of a document.
		///
		/// <param name="document">The document to create HTML from.</param>
		/// <param name="highlighter">The highlighter used to highlight the document. <c>null</c> is valid and will create HTML without any highlighting.</param>
		/// <param name="segment">The part of the document to create HTML for. You can pass <c>null</c> to create HTML for the whole document.</param>
		/// <param name="options">The options for the HTML creation.</param>
		/// <returns>HTML code for the document part.</returns>
		public static string CreateHtmlFragment(TextDocument document, IHighlighter highlighter, ISegment segment, HtmlOptions options)
		{
			if (document == null)
				throw new ArgumentNullException("document");
			if (options == null)
				throw new ArgumentNullException("options");
			if (highlighter != null && highlighter.Document != document)
				throw new ArgumentException("Highlighter does not belong to the specified document.");
			if (segment == null)
				segment = new SimpleSegment(0, document.TextLength);

			StringBuilder html = new StringBuilder();
			int segmentEndOffset = segment.EndOffset;
			DocumentLine line = document.GetLineByOffset(segment.Offset);
			while (line != null && line.Offset < segmentEndOffset) {
				HighlightedLine highlightedLine;
				if (highlighter != null)
					highlightedLine = highlighter.HighlightLine(line.LineNumber);
				else
					highlightedLine = new HighlightedLine(document, line);
				SimpleSegment s = segment.GetOverlap(line);
				if (html.Length > 0)
					html.AppendLine("
");
				html.Append(highlightedLine.ToHtml(s.Offset, s.EndOffset, options));
				line = line.NextLine;
			}
			return html.ToString();
		}

		///
		/// Escapes text and writes the result to the StringBuilder.
		///
		internal static void EscapeHtml(StringWriter w, string text, HtmlOptions options)
		{
			int spaceCount = -1;
			foreach (char c in text) {
				if (c == ' ') {
					if (spaceCount < 0)
						w.Write(" ");
					else
						spaceCount++;
				} else if (c == '\t') {
					if (spaceCount < 0)
						spaceCount = 0;
					spaceCount += options.TabSize;
				} else {
					if (spaceCount == 1) {
						w.Write(' ');
					} else if (spaceCount >= 1) {
						for (int i = 0; i < spaceCount; i++) {
							w.Write(" ");
						}
					}
					spaceCount = 0;
					switch (c) {
						case '<':
							w.Write("<");
							break;
						case '>':
							w.Write(">");
							break;
						case '&':
							w.Write("&");
							break;
						case '"':
							w.Write(""");
							break;
						default:
							w.Write(c);
							break;
					}
				}
			}
			for (int i = 0; i < spaceCount; i++) {
				w.Write(" ");
			}
		}
	}

	///
	/// Holds options for converting text to HTML.
	///
	public class HtmlOptions
	{
		///
		/// Creates a default HtmlOptions instance.
		///
		public HtmlOptions()
		{
			this.TabSize = 4;
		}

		///
		/// Creates a new HtmlOptions instance that copies applicable options from the <see cref="TextEditorOptions"/>.
		///
		public HtmlOptions(TextEditorOptions options)
			: this()
		{
			if (options == null)
				throw new ArgumentNullException("options");
			this.TabSize = options.IndentationSize;
		}

		///
		/// The amount of spaces a tab gets converted to.
		///
		public int TabSize { get; set; }

		///
		/// Writes the HTML attribute for the style to the text writer.
		///
		public virtual void WriteStyleAttributeForColor(TextWriter writer, HighlightingColor color)
		{
			if (writer == null)
				throw new ArgumentNullException("writer");
			if (color == null)
				throw new ArgumentNullException("color");
			writer.Write(" style=\"");
			writer.Write(color.ToCss());
			writer.Write("\"");
		}

		///
		/// Gets whether the color needs to be written out to HTML.
		///
		public virtual bool ColorNeedsSpanForStyling(HighlightingColor color)
		{
			if (color == null)
				throw new ArgumentNullException("color");
			return !string.IsNullOrEmpty(color.ToCss());
		}
	}
}


text:
require 'rubygems'

require 'iup'

calc = {}

  text = Iup.Text(:size=>"100x20")

	calc_end = lambda do
	  Iup.SetIdle(nil)
	  Iup::DEFAULT
	end

	idle_function = lambda do
	  # Iup::TITLE value for IUP */
	  sleep 0.01
	  calc[:passo]+= 1 # next iteration step */
	  calc[:fatorial] *= calc[:passo] # executes one computation step */

	  # feedback to the user on the current step and the last computed value */
	  str = "%d -> %10.4g" % [calc[:passo],calc[:fatorial]]
	  text.value = str

	  if(calc[:passo] == 100) # computation ends when step = 100 */
	    calc_end.call
	  end
	  Iup::DEFAULT
	end

	calc_begin = lambda do |ih|
	  calc[:passo] = 0
	  calc[:fatorial] = 1.0
	  Iup.SetIdle(idle_function)
	  text.value = "Computing..."
	  Iup::DEFAULT
	end

  bt = Iup.Button(:title=>"Calcular",:action=>calc_begin)

  dg = Iup.Dialog(Iup.Vbox([text, bt]))

  dg.ShowXY(Iup::CENTER, Iup::CENTER)

  Iup.MainLoop()
  dg.Destroy()


text:
layout: default
title: Cultura y Turismo
permalink: /herramientas/cultura-y-turismo/
---

{% include apps_header.html highlight='all' %}

                {% include sidebar.html highlight='culture' section='herramientas' %}

                {% assign posts = site.posts | where: 'section', 'herramientas' | where: 'category', 'cultura-y-turismo' | where: 'published', true | sort: 'date' %}
                {% include tools_container.html posts=posts section='herramientas' %}


text:
ACCEPTED

#### According to
Index Fungorum

#### Published in
Syll. fung. (Abellini) 5: 66 (1887)

#### Original name
Agaricus leontoderes Berk. & Broome

### Remarks
null


text:
<?php

namespace Humbug\SelfUpdate;

class VersionParser
{

    /**
     * @var array
     */
    private $versions;

    /**
     * @var string
     */
    private $modifier = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)(?:[.-]?(\d+))?)?([.-]?dev)?';

    /**
     * @param array $versions
     */
    public function __construct(array $versions = [])
    {
        $this->versions = $versions;
    }

    /**
     * Get the most recent stable numbered version from versions passed to
     * constructor (if any)
     *
     * @return string
     */
    public function getMostRecentStable()
    {
        return $this->selectRecentStable();
    }

    /**
     * Get the most recent unstable numbered version from versions passed to
     * constructor (if any)
     *
     * @return string
     */
    public function getMostRecentUnStable()
    {
        return $this->selectRecentUnstable();
    }

    /**
     * Get the most recent stable or unstable numbered version from versions passed to
     * constructor (if any)
     *
     * @return string
     */
    public function getMostRecentAll()
    {
        return $this->selectRecentAll();
    }

    /**
     * Checks if given version string represents a stable numbered version
     *
     * @param string $version
     * @return bool
     */
    public function isStable($version)
    {
        return $this->stable($version);
    }

    /**
     * Checks if given version string represents a 'pre-release' version, i.e.
     * it's unstable but not development level.
     *
     * @param string $version
     * @return bool
     */
    public function isPreRelease($version)
    {
        return !$this->stable($version) && !$this->development($version);
    }

    /**
     * Checks if given version string represents an unstable or dev-level
     * numbered version
     *
     * @param string $version
     * @return bool
     */
    public function isUnstable($version)
    {
        return !$this->stable($version);
    }

    /**
     * Checks if given version string represents a dev-level numbered version
     *
     * @param string $version
     * @return bool
     */
    public function isDevelopment($version)
    {
        return $this->development($version);
    }

    private function selectRecentStable()
    {
        $candidates = [];
        foreach ($this->versions as $version) {
            if (!$this->stable($version)) {
                continue;
            }
            $candidates[] = $version;
        }
        if (empty($candidates)) {
            return false;
        }
        return $this->findMostRecent($candidates);
    }

    private function selectRecentUnstable()
    {
        $candidates = [];
        foreach ($this->versions as $version) {
            if ($this->stable($version) || $this->development($version)) {
                continue;
            }
            $candidates[] = $version;
        }
        if (empty($candidates)) {
            return false;
        }
        return $this->findMostRecent($candidates);
    }

    private function selectRecentAll()
    {
        $candidates = [];
        foreach ($this->versions as $version) {
            if ($this->development($version)) {
                continue;
            }
            $candidates[] = $version;
        }
        if (empty($candidates)) {
            return false;
        }
        return $this->findMostRecent($candidates);
    }

    private function findMostRecent(array $candidates)
    {
        $candidate = null;
        $tracker = null;
        foreach ($candidates as $version) {
            if (version_compare($candidate, $version, '<')) {
                $candidate = $version;
            }
        }
        return $candidate;
    }

    private function stable($version)
    {
        $version = preg_replace('{#.+$}i', '', $version);
        if ($this->development($version)) {
            return false;
        }
        preg_match('{'.$this->modifier.'$}i', strtolower($version), $match);
        if (!empty($match[3])) {
            return false;
        }
        if (!empty($match[1])) {
            if ('beta' === $match[1] || 'b' === $match[1]
            || 'alpha' === $match[1] || 'a' === $match[1]
            || 'rc' === $match[1]) {
                return false;
            }
        }
        return true;
    }

    private function development($version)
    {
        if ('dev-' === substr($version, 0, 4) || '-dev' === substr($version, -4)) {
            return true;
        }
        return false;
    }
}


text:
#ifndef __CONTOURSHAPEEXTRACTION_H__
#define __CONTOURSHAPEEXTRACTION_H__

#include <visor/MPEG7FexLib_src_OpenCV22/AddressLib/vopio.h>

namespace XM
{

class ContourShapeExtractionTool
{
public:
	ContourShapeExtractionTool();
	~ContourShapeExtractionTool();

	ContourShapeDescriptor* GetDescriptor();
	int SetDescriptor(ContourShapeDescriptor* aContourShapeDescriptor);

	// background : 0, foreground: 255
	// alpha channel (a_chan) or y_chan of MomVop image is the object mask
	unsigned long extract(MomVop *img);
	// TODO: modify this function to take a single channel MomImage as a parameter

private:

	ContourShapeDescriptor* m_Descriptor;
	MomVop* m_ImageMedia;

	// functions used for extracting the contour shape and the
	// peaks from the contour...
	unsigned long ExtractContour(int n, Point2* const &coords);
	unsigned long ExtractPeaks(int n, const Point2* const &coords);

	// function to extract the curvature values (eccentricity and
	// circularity) from the contour...
	void ExtractCurvature(int n, const Point2 * const &coords, unsigned long &cir, unsigned long &ecc);
};

};

#endif


text:
require 'spec_helper'
require 'pul_metadata_services'

vcr_options = {
  record: :new_episodes,
  serialize_with: :json
}

describe PulMetadataServices::Client, vcr: vcr_options do

  let(:fixture_path) { File.expand_path('../../fixtures', __FILE__) }
  let(:marcxml) { File.open(File.join(fixture_path, '4609321.mrx')).read.strip }
  let(:ead) { File.open(File.join(fixture_path, 'AC044_c0003.xml')).read.strip }
  let(:ead_full) { File.open(File.join(fixture_path, 'AC044_c0003_full.xml')).read.strip }
  let(:ead2) { File.open(File.join(fixture_path, 'RBD1_c13076.xml')).read.strip }
  before do
    VCR.turn_on!
  end

  context 'with a Voyager-like id' do
    it 'makes requests to Voyager' do
      expect(described_class.retrieve('4609321').source).to eq marcxml
      expect(described_class.retrieve('4609321').full_source).to eq marcxml
    end
  end
  context 'with a Pulfa-like id' do
    it 'makes requests to PULFA' do
      output = described_class.retrieve('AC044_c0003')
      expect(output.source).to eq ead
      expect(output.full_source).to eq ead_full
    end
  end
  context 'with a Pulfa-like id, when the metadata contains non-ASCII characters' do
    it 'makes requests to PULFA and parses character encoding correctly' do
      expect(described_class.retrieve('RBD1_c13076').source).to eq ead2
    end
  end
end


text:
// Copyright 2009 the Sputnik authors.  All rights reserved.
/**
 * String.prototype.split (separator, limit) returns an Array object into which substrings of the result of converting this object to a string have
 * been stored. The substrings are determined by searching from left to right for occurrences of
 * separator; these occurrences are not part of any substring in the returned array, but serve to divide up
 * the string value. The value of separator may be a string of any length or it may be a RegExp object
 *
 * @path ch15/15.5/15.5.4/15.5.4.14/S15.5.4.14_A2_T9.js
 * @description Call split(true), instance is "thistrueistrueatruestringtrueobject"
 */

var __string = "thistrueistrueatruestringtrueobject";
var __expected = ["this", "is", "a", "string", "object"];

var __split = __string.split(true);

//////////////////////////////////////////////////////////////////////////////
//CHECK#1
if (__split.constructor !== Array) {
  $ERROR('#1: var __string = "thistrueistrueatruestringtrueobject"; var __expected = ["this", "is", "a", "string", "object"]; __split = __string.split(true); __split.constructor === Array. Actual: '+__split.constructor );
}
//
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
//CHECK#2
if (__split.length !== __expected.length) {
  $ERROR('#2: var __string = "thistrueistrueatruestringtrueobject"; var __expected = ["this", "is", "a", "string", "object"]; __split = __string.split(true); __split.length === __expected.length. Actual: '+__split.length );
}
//
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
//CHECK#3
for ( var i = 0; i < __expected.length; i++ ) {
    if (__expected[i]!==__split[i]) {
      $ERROR('#3.'+i+': var __string = "thistrueistrueatruestringtrueobject"; var __expected = ["this", "is", "a", "string", "object"]; __split = __string.split(true); __expected['+i+']==='+__split[i]+'. Actual: '+__expected[i]);
    }
}
//
//////////////////////////////////////////////////////////////////////////////


text:
"""Google이나 Facebook 같은 외부 서비스에서 제공하는 인증 정보를 다룹니다.

"""
import collections

from sqlalchemy import types, sql, orm
from sqlalchemy.schema import Column, ForeignKey
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.dialects import postgresql

from .base import Base, GUID
from .user import User

__all__ = ['Credential', 'GoogleOAuth2']

class Credential(Base):
    """:class:`User`\ 가 가진 인증 수단"""
    __tablename__ = 'credential'

    user_pk = Column(GUID, ForeignKey(User.pk, onupdate='CASCADE',
                                               ondelete='CASCADE'),
                     primary_key=True)
    cred_type = Column(types.Unicode(20), primary_key=True)
    key = Column(types.Unicode(256), primary_key=True)
    value = Column(postgresql.HSTORE, nullable=False)
    created_at = Column(types.DateTime(timezone=True),
                        default=sql.functions.now())
    updated_at = Column(types.DateTime(timezone=True),
                        onupdate=sql.functions.now())

    user = orm.relationship(User)

    __mapper_args__ = {
        'polymorphic_on': cred_type,
    }

class GoogleOAuth2(Credential):
    """Google OAuth2 인증

    .. seealso:: `Using OAuth 2.0 for Login <https://developers.google.com/accounts/docs/OAuth2Login>`_

    """
    __mapper_args__ = {
        'polymorphic_identity': 'google_oauth2',
    }

    def __init__(self, user, token, user_key=None):
        """

        :param midauth.models.user.User user:
        :param dict token:

        """
        self.user = user
        self.key = user_key
        self.token = token

    @hybrid_property
    def token(self):
        return self.value

    @token.setter
    def token(self, value):
        if not isinstance(value, collections.Mapping):
            raise TypeError('value should be a collections.Mapping, not {0!r}'
                            .format(value))
        self.value = dict((k, unicode(v)) for k, v in value.iteritems())

    @orm.validates('token')
    def validate_token(self, key, token):
        assert 'access_token' in token


text:
@interface TTTableMessageItem : TTTableTextItem {
  NSString* _title;
  NSString* _caption;
  NSDate*   _timestamp;
  NSString* _imageURL;
}

@property (nonatomic, copy)   NSString* title;
@property (nonatomic, copy)   NSString* caption;
@property (nonatomic, retain) NSDate*   timestamp;
@property (nonatomic, copy)   NSString* imageURL;

+ (id)itemWithTitle:(NSString*)title caption:(NSString*)caption text:(NSString*)text
          timestamp:(NSDate*)timestamp URL:(NSString*)URL;
+ (id)itemWithTitle:(NSString*)title caption:(NSString*)caption text:(NSString*)text
          timestamp:(NSDate*)timestamp imageURL:(NSString*)imageURL URL:(NSString*)URL;

@end


text:
package com.wenyu.Utils;

import android.content.Context;
import android.content.res.Resources;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.wenyu.kaijiw.R;

public class TipsToast extends Toast {
	public TipsToast(Context context) {
		super(context);
	}

	public static TipsToast makeText(Context context, CharSequence text, int duration) {
		TipsToast result = new TipsToast(context);

		LayoutInflater layoutInflater = (LayoutInflater) context
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View view = layoutInflater.inflate(R.layout.view_tips, null);
		TextView textView = (TextView) view.findViewById(R.id.tips_msg);

		textView.setText(text);
		result.setView(view);

		// setGravity方法用于设置位置,此处为垂直居中
		result.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
		result.setDuration(duration);

		return result;
	}

	public static TipsToast makeText(Context context, int resId, int duration)
			throws Resources.NotFoundException {
		return makeText(context, context.getResources().getText(resId), duration);
	}

	public void setIcon(int iconResId) {
		if (getView() == null) {
			throw new RuntimeException(
					"This Toast was not created with Toast.makeText()");
		}

		ImageView imageView = (ImageView) getView().findViewById(R.id.tips_icon);

		if (imageView == null) {
			throw new RuntimeException(
					"This Toast was not created with Toast.makeText()");
		}

		imageView.setImageResource(iconResId);
	}

	@Override
	public void setText(CharSequence s) {
		if (getView() == null) {
			throw new RuntimeException(
					"This Toast was not created with Toast.makeText()");
		}

		TextView textView = (TextView) getView().findViewById(R.id.tips_msg);

		if (textView == null) {
			throw new RuntimeException(
					"This Toast was not created with Toast.makeText()");
		}

		textView.setText(s);
	}
}


text:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var ImageSchema = new Schema({
  imageData: String
})


text:
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2016-2020 Authors of Cilium */

#ifndef __LIB_CONNTRACK_H_
#define __LIB_CONNTRACK_H_

#include <linux/icmpv6.h>
#include <linux/icmp.h>

#include "common.h"
#include "utils.h"
#include "ipv4.h"
#include "ipv6.h"
#include "dbg.h"
#include "l4.h"
#include "nat46.h"
#include "signal.h"

#ifdef CONNTRACK
enum {
	ACTION_UNSPEC,
	ACTION_CREATE,
	ACTION_CLOSE,
};

/* conn_is_dns returns true if the connection is DNS, false otherwise.
 *
 * @dport: Connection destination port.
 *
 * To reduce program complexity, we ignore nexthdr and dir here:
 * nexthdr: The parser will not fill dport if nexthdr is not TCP/UDP.
 * dir:     Ideally we would only consider responses, but requests are likely
 *          to be small anyway.
 */
static __always_inline bool conn_is_dns(__u16 dport)
{
	return dport == bpf_htons(53);
}

union tcp_flags {
	struct {
		__u8 upper_bits;
		__u8 lower_bits;
		__u16 pad;
	};
	__u32 value;
};

/**
 * Update the CT timeout and TCP flags for the specified entry.
 *
 * We track the OR'd accumulation of seen tcp flags in the entry, and the
 * last time that a notification was sent. Multiple CPUs may enter this
 * function with packets for the same connection, in which case it is possible
 * for the CPUs to race to update the entry. In such a case, the critical
 * update section may be entered in quick succession, leading to multiple
 * updates of the entry and returning true for each CPU. The BPF architecture
 * guarantees that entire 8-bit or 32-bit values will be set within the entry,
 * so although the CPUs may race, the worst result is that multiple executions
 * of this function return non-zero for the same connection within short
 * succession, leading to multiple trace notifications being sent when one
 * might otherwise expect such notifications to be aggregated.
 *
 * Returns how many bytes of the packet should be monitored:
 * - Zero if this flow was recently monitored.
 * - Non-zero if this flow has not been monitored recently.
 */
static __always_inline __u32 __ct_update_timeout(struct ct_entry *entry,
						 __u32 lifetime, int dir,
						 union tcp_flags flags,
						 __u8 report_mask)
{
	__u32 now = bpf_mono_now();
	__u8 accumulated_flags;
	__u8 seen_flags = flags.lower_bits & report_mask;
	__u32 last_report;

#ifdef NEEDS_TIMEOUT
	WRITE_ONCE(entry->lifetime, now + lifetime);
#endif
	if (dir == CT_INGRESS) {
		accumulated_flags = READ_ONCE(entry->rx_flags_seen);
		last_report = READ_ONCE(entry->last_rx_report);
	} else {
		accumulated_flags = READ_ONCE(entry->tx_flags_seen);
		last_report = READ_ONCE(entry->last_tx_report);
	}
	seen_flags |= accumulated_flags;

	/* It's possible for multiple CPUs to execute the branch statement here
	 * one after another, before the first CPU is able to execute the entry
	 * modifications within this branch. This is somewhat unlikely because
	 * packets for the same connection are typically steered towards the
	 * same CPU, but is possible in theory.
	 *
	 * If the branch is taken by multiple CPUs because of '*last_report',
	 * then this merely causes multiple notifications to be sent after
	 * CT_REPORT_INTERVAL rather than a single notification. '*last_report'
	 * will be updated by all CPUs and subsequent checks should not take
	 * this branch until the next CT_REPORT_INTERVAL. As such, the trace
	 * aggregation that uses the result of this function may reduce the
	 * number of packets per interval to a small integer value (max N_CPUS)
	 * rather than 1 notification per packet throughout the interval.
	 *
	 * Similar behaviour may happen with tcp_flags. The worst case race
	 * here would be that two or more CPUs argue over which flags have been
	 * seen and overwrite each other, with each CPU interleaving different
	 * values for which flags were seen. In practice, realistic connections
	 * are likely to progressively set SYN, ACK, then much later perhaps
	 * FIN and/or RST. Furthermore, unless such a traffic pattern were
	 * constantly received, this should self-correct as the stored
	 * tcp_flags is an OR'd set of flags and each time the above code is
	 * executed, it pulls the latest set of accumulated flags. Therefore
	 * even in the worst case such a conflict is likely only to cause a
	 * small number of additional notifications, which is still likely to
	 * be significantly less under this MONITOR_AGGREGATION mode than would
	 * otherwise be sent if the MONITOR_AGGREGATION level is set to none
	 * (ie, sending a notification for every packet).
	 */
	if (last_report + bpf_sec_to_mono(CT_REPORT_INTERVAL) < now ||
	    accumulated_flags != seen_flags) {
		/* verifier workaround: we don't use reference here. */
		if (dir == CT_INGRESS) {
			WRITE_ONCE(entry->rx_flags_seen, seen_flags);
			WRITE_ONCE(entry->last_rx_report, now);
		} else {
			WRITE_ONCE(entry->tx_flags_seen, seen_flags);
			WRITE_ONCE(entry->last_tx_report, now);
		}
		return TRACE_PAYLOAD_LEN;
	}
	return 0;
}

/**
 * Update the CT timeouts for the specified entry.
 *
 * If CT_REPORT_INTERVAL has elapsed since the last update, updates the
 * last_updated timestamp and returns true. Otherwise returns false.
 */
static __always_inline __u32 ct_update_timeout(struct ct_entry *entry,
					       bool tcp, int dir,
					       union tcp_flags seen_flags)
{
	__u32 lifetime = dir == CT_SERVICE ?
			 bpf_sec_to_mono(CT_SERVICE_LIFETIME_NONTCP) :
			 bpf_sec_to_mono(CT_CONNECTION_LIFETIME_NONTCP);
	bool syn = seen_flags.value & TCP_FLAG_SYN;

	if (tcp) {
		entry->seen_non_syn |= !syn;
		if (entry->seen_non_syn) {
			lifetime = dir == CT_SERVICE ?
				   bpf_sec_to_mono(CT_SERVICE_LIFETIME_TCP) :
				   bpf_sec_to_mono(CT_CONNECTION_LIFETIME_TCP);
		} else {
			lifetime = bpf_sec_to_mono(CT_SYN_TIMEOUT);
		}
	}

	return __ct_update_timeout(entry, lifetime, dir, seen_flags,
				   CT_REPORT_FLAGS);
}

static __always_inline void ct_reset_closing(struct ct_entry *entry)
{
	entry->rx_closing = 0;
	entry->tx_closing = 0;
}

static __always_inline bool ct_entry_alive(const struct ct_entry *entry)
{
	return !entry->rx_closing || !entry->tx_closing;
}

/* Helper for holding 2nd service entry alive in nodeport case. */
static __always_inline bool __ct_entry_keep_alive(const void *map,
						  const void *tuple)
{
	struct ct_entry *entry;

	/* Lookup indicates to LRU that key/value is in use. */
	entry = map_lookup_elem(map, tuple);
	if (entry) {
		if (entry->node_port) {
#ifdef NEEDS_TIMEOUT
			__u32 lifetime = (entry->seen_non_syn ?
					  bpf_sec_to_mono(CT_SERVICE_LIFETIME_TCP) :
					  bpf_sec_to_mono(CT_SERVICE_LIFETIME_NONTCP)) +
					 bpf_mono_now();
			WRITE_ONCE(entry->lifetime, lifetime);
#endif
			if (!ct_entry_alive(entry))
				ct_reset_closing(entry);
		}
		return true;
	}
	return false;
}

static __always_inline __u8 __ct_lookup(const void *map, struct __ctx_buff *ctx,
					const void *tuple, int action, int dir,
					struct ct_state *ct_state,
					bool is_tcp, union tcp_flags seen_flags,
					__u32 *monitor)
{
	struct ct_entry *entry;
	int reopen;

	entry = map_lookup_elem(map, tuple);
	if (entry) {
		cilium_dbg(ctx, DBG_CT_MATCH, entry->lifetime, entry->rev_nat_index);
		if (ct_entry_alive(entry))
			*monitor = ct_update_timeout(entry, is_tcp, dir, seen_flags);
		if (ct_state) {
			ct_state->rev_nat_index = entry->rev_nat_index;
			ct_state->loopback = entry->lb_loopback;
			ct_state->node_port = entry->node_port;
			ct_state->ifindex = entry->ifindex;
			ct_state->dsr = entry->dsr;
			ct_state->proxy_redirect = entry->proxy_redirect;
			if (dir == CT_SERVICE)
				ct_state->backend_id = entry->rx_bytes;
		}

#ifdef ENABLE_NAT46
		/* This packet needs nat46 translation */
		if (entry->nat46 && !ctx_load_meta(ctx, CB_NAT46_STATE))
			ctx_store_meta(ctx, CB_NAT46_STATE, NAT46);
#endif
#ifdef CONNTRACK_ACCOUNTING
		/* FIXME: This is slow, per-cpu counters? */
		if (dir == CT_INGRESS) {
			__sync_fetch_and_add(&entry->rx_packets, 1);
			__sync_fetch_and_add(&entry->rx_bytes, ctx_full_len(ctx));
		} else if (dir == CT_EGRESS) {
			__sync_fetch_and_add(&entry->tx_packets, 1);
			__sync_fetch_and_add(&entry->tx_bytes, ctx_full_len(ctx));
		}
#endif
		switch (action) {
		case ACTION_CREATE:
			reopen = entry->rx_closing | entry->tx_closing;
			reopen |= seen_flags.value & TCP_FLAG_SYN;
			if (unlikely(reopen == (TCP_FLAG_SYN|0x1))) {
				ct_reset_closing(entry);
				*monitor = ct_update_timeout(entry, is_tcp, dir, seen_flags);
			}
			break;
		case ACTION_CLOSE:
			/* RST or similar, immediately delete ct entry */
			if (dir == CT_INGRESS)
				entry->rx_closing = 1;
			else
				entry->tx_closing = 1;

			*monitor = TRACE_PAYLOAD_LEN;
			if (ct_entry_alive(entry))
				break;
			__ct_update_timeout(entry, bpf_sec_to_mono(CT_CLOSE_TIMEOUT),
					    dir, seen_flags, CT_REPORT_FLAGS);
			break;
		}

		return CT_ESTABLISHED;
	}

	*monitor = TRACE_PAYLOAD_LEN;
	return CT_NEW;
}

static __always_inline int
ipv6_extract_tuple(struct __ctx_buff *ctx, struct ipv6_ct_tuple *tuple,
		   int *l4_off)
{
	int ret, l3_off = ETH_HLEN;
	void *data, *data_end;
	struct ipv6hdr *ip6;

	if (!revalidate_data(ctx, &data, &data_end, &ip6))
		return DROP_INVALID;

	tuple->nexthdr = ip6->nexthdr;
	ipv6_addr_copy(&tuple->daddr, (union v6addr *)&ip6->daddr);
	ipv6_addr_copy(&tuple->saddr, (union v6addr *)&ip6->saddr);

	ret = ipv6_hdrlen(ctx, l3_off, &tuple->nexthdr);
	if (ret < 0)
		return ret;

	if (unlikely(tuple->nexthdr != IPPROTO_TCP &&
		     tuple->nexthdr != IPPROTO_UDP))
		return DROP_CT_UNKNOWN_PROTO;

	if (ret < 0)
		return ret;

	*l4_off = l3_off + ret;
	return CTX_ACT_OK;
}

static __always_inline void ct_flip_tuple_dir6(struct ipv6_ct_tuple *tuple)
{
	if (tuple->flags & TUPLE_F_IN)
		tuple->flags &= ~TUPLE_F_IN;
	else
		tuple->flags |= TUPLE_F_IN;
}

static __always_inline void
__ipv6_ct_tuple_reverse(struct ipv6_ct_tuple *tuple)
{
	union v6addr tmp_addr = {};
	__be16 tmp;

	ipv6_addr_copy(&tmp_addr, &tuple->saddr);
	ipv6_addr_copy(&tuple->saddr, &tuple->daddr);
	ipv6_addr_copy(&tuple->daddr, &tmp_addr);

	tmp = tuple->sport;
	tuple->sport = tuple->dport;
	tuple->dport = tmp;
}

static __always_inline void
ipv6_ct_tuple_reverse(struct ipv6_ct_tuple *tuple)
{
	__ipv6_ct_tuple_reverse(tuple);
	ct_flip_tuple_dir6(tuple);
}

/* Offset must point to IPv6 */
static __always_inline int ct_lookup6(const void *map,
				      struct ipv6_ct_tuple *tuple,
				      struct __ctx_buff *ctx, int l4_off,
				      int dir, struct ct_state *ct_state,
				      __u32 *monitor)
{
	int ret = CT_NEW, action = ACTION_UNSPEC;
	bool is_tcp = tuple->nexthdr == IPPROTO_TCP;
	union tcp_flags tcp_flags = { .value = 0 };

	/* The tuple is created in reverse order initially to find a
	 * potential reverse flow. This is required because the RELATED
	 * or REPLY state takes precedence over ESTABLISHED due to
	 * policy requirements.
	 *
	 * tuple->flags separates entries that could otherwise be overlapping.
	 */
	if (dir == CT_INGRESS)
		tuple->flags = TUPLE_F_OUT;
	else if (dir == CT_EGRESS)
		tuple->flags = TUPLE_F_IN;
	else if (dir == CT_SERVICE)
		tuple->flags = TUPLE_F_SERVICE;
	else
		return DROP_CT_INVALID_HDR;

	switch (tuple->nexthdr) {
	case IPPROTO_ICMPV6:
		if (1) {
			__be16 identifier = 0;
			__u8 type;

			if (ctx_load_bytes(ctx, l4_off, &type, 1) < 0)
				return DROP_CT_INVALID_HDR;
			if ((type == ICMPV6_ECHO_REQUEST || type == ICMPV6_ECHO_REPLY) &&
			     ctx_load_bytes(ctx, l4_off + offsetof(struct icmp6hdr,
								   icmp6_dataun.u_echo.identifier),
					    &identifier, 2) < 0)
				return DROP_CT_INVALID_HDR;

			tuple->sport = 0;
			tuple->dport = 0;

			switch (type) {
			case ICMPV6_DEST_UNREACH:
			case ICMPV6_PKT_TOOBIG:
			case ICMPV6_TIME_EXCEED:
			case ICMPV6_PARAMPROB:
				tuple->flags |= TUPLE_F_RELATED;
				break;

			case ICMPV6_ECHO_REQUEST:
			case ICMPV6_ECHO_REPLY:
				if (dir == CT_INGRESS)
					tuple->sport = identifier;
				else
					tuple->dport = identifier;
				/* fall through */
			default:
				action = ACTION_CREATE;
				break;
			}
		}
		break;

	case IPPROTO_TCP:
		if (1) {
			if (ctx_load_bytes(ctx, l4_off + 12, &tcp_flags, 2) < 0)
				return DROP_CT_INVALID_HDR;

			if (unlikely(tcp_flags.value & (TCP_FLAG_RST|TCP_FLAG_FIN)))
				action = ACTION_CLOSE;
			else
				action = ACTION_CREATE;
		}

		/* load sport + dport into tuple */
		if (ctx_load_bytes(ctx, l4_off, &tuple->dport, 4) < 0)
			return DROP_CT_INVALID_HDR;
		break;

	case IPPROTO_UDP:
		/* load sport + dport into tuple */
		if (ctx_load_bytes(ctx, l4_off, &tuple->dport, 4) < 0)
			return DROP_CT_INVALID_HDR;

		action = ACTION_CREATE;
		break;

	default:
		/* Can't handle extension headers yet */
		return DROP_CT_UNKNOWN_PROTO;
	}

	/* Lookup the reverse direction
	 *
	 * This will find an existing flow in the reverse direction.
	 * The reverse direction is the one where reverse nat index is stored.
	 */
	cilium_dbg3(ctx, DBG_CT_LOOKUP6_1, (__u32) tuple->saddr.p4, (__u32) tuple->daddr.p4,
		      (bpf_ntohs(tuple->sport) << 16) | bpf_ntohs(tuple->dport));
	cilium_dbg3(ctx, DBG_CT_LOOKUP6_2, (tuple->nexthdr << 8) | tuple->flags, 0, 0);
	ret = __ct_lookup(map, ctx, tuple, action, dir, ct_state, is_tcp,
			  tcp_flags, monitor);
	if (ret != CT_NEW) {
		if (likely(ret == CT_ESTABLISHED)) {
			if (unlikely(tuple->flags & TUPLE_F_RELATED))
				ret = CT_RELATED;
			else
				ret = CT_REPLY;
		}
		goto out;
	}

	/* Lookup entry in forward direction */
	if (dir != CT_SERVICE) {
		ipv6_ct_tuple_reverse(tuple);
		ret = __ct_lookup(map, ctx, tuple, action, dir, ct_state,
				  is_tcp, tcp_flags, monitor);
	}

#ifdef ENABLE_NAT46
	ctx_store_meta(ctx, CB_NAT46_STATE, NAT46_CLEAR);
#endif
out:
	cilium_dbg(ctx, DBG_CT_VERDICT, ret < 0 ? -ret : ret, ct_state->rev_nat_index);
	if (conn_is_dns(tuple->dport))
		*monitor = MTU;
	return ret;
}

static __always_inline int
ipv4_extract_tuple(struct __ctx_buff *ctx, struct ipv4_ct_tuple *tuple,
		   int *l4_off)
{
	int l3_off = ETH_HLEN;
	void *data, *data_end;
	struct iphdr *ip4;

	if (!revalidate_data(ctx, &data, &data_end, &ip4))
		return DROP_INVALID;

	tuple->nexthdr = ip4->protocol;

	if (unlikely(tuple->nexthdr != IPPROTO_TCP &&
		     tuple->nexthdr != IPPROTO_UDP))
		return DROP_CT_UNKNOWN_PROTO;

	tuple->daddr = ip4->daddr;
	tuple->saddr = ip4->saddr;

	*l4_off = l3_off + ipv4_hdrlen(ip4);
	return CTX_ACT_OK;
}

static __always_inline void ct_flip_tuple_dir4(struct ipv4_ct_tuple *tuple)
{
	if (tuple->flags & TUPLE_F_IN)
		tuple->flags &= ~TUPLE_F_IN;
	else
		tuple->flags |= TUPLE_F_IN;
}

static __always_inline void
__ipv4_ct_tuple_reverse(struct ipv4_ct_tuple *tuple)
{
	__be32 tmp_addr = tuple->saddr;
	__be16 tmp;

	tuple->saddr = tuple->daddr;
	tuple->daddr = tmp_addr;

	tmp = tuple->sport;
	tuple->sport = tuple->dport;
	tuple->dport = tmp;
}

static __always_inline void
ipv4_ct_tuple_reverse(struct ipv4_ct_tuple *tuple)
{
	__ipv4_ct_tuple_reverse(tuple);
	ct_flip_tuple_dir4(tuple);
}

static __always_inline int ipv4_ct_extract_l4_ports(struct __ctx_buff *ctx,
						    int off,
						    struct ipv4_ct_tuple *tuple)
{
#ifdef ENABLE_IPV4_FRAGMENTS
	void *data, *data_end;
	struct iphdr *ip4;

	/* This function is called from ct_lookup4(), which is sometimes called
	 * after data has been invalidated (see handle_ipv4_from_lxc())
	 */
	if (!revalidate_data(ctx, &data, &data_end, &ip4))
		return DROP_INVALID;

	if (unlikely(ipv4_is_fragment(ip4)))
		return ipv4_handle_fragment(ctx, ip4, off,
					    (struct ipv4_frag_l4ports *)&tuple->dport);
#endif
	/* load sport + dport into tuple */
	return ctx_load_bytes(ctx, off, &tuple->dport, 4);
}

static __always_inline void ct4_cilium_dbg_tuple(struct __ctx_buff *ctx, __u8 type,
						 const struct ipv4_ct_tuple *tuple,
						 __u32 rev_nat_index, int dir)
{
	__be32 addr = (dir == CT_INGRESS) ? tuple->saddr : tuple->daddr;

	cilium_dbg(ctx, type, addr, rev_nat_index);
}

/* Offset must point to IPv4 header */
static __always_inline int ct_lookup4(const void *map,
				      struct ipv4_ct_tuple *tuple,
				      struct __ctx_buff *ctx, int off, int dir,
				      struct ct_state *ct_state, __u32 *monitor)
{
	int ret = CT_NEW, action = ACTION_UNSPEC;
	bool is_tcp = tuple->nexthdr == IPPROTO_TCP;
	union tcp_flags tcp_flags = { .value = 0 };

	/* The tuple is created in reverse order initially to find a
	 * potential reverse flow. This is required because the RELATED
	 * or REPLY state takes precedence over ESTABLISHED due to
	 * policy requirements.
	 *
	 * tuple->flags separates entries that could otherwise be overlapping.
	 */
	if (dir == CT_INGRESS)
		tuple->flags = TUPLE_F_OUT;
	else if (dir == CT_EGRESS)
		tuple->flags = TUPLE_F_IN;
	else if (dir == CT_SERVICE)
		tuple->flags = TUPLE_F_SERVICE;
	else
		return DROP_CT_INVALID_HDR;

	switch (tuple->nexthdr) {
	case IPPROTO_ICMP:
		if (1) {
			__be16 identifier = 0;
			__u8 type;

			if (ctx_load_bytes(ctx, off, &type, 1) < 0)
				return DROP_CT_INVALID_HDR;
			if ((type == ICMP_ECHO || type == ICMP_ECHOREPLY) &&
			     ctx_load_bytes(ctx, off + offsetof(struct icmphdr, un.echo.id),
					    &identifier, 2) < 0)
				return DROP_CT_INVALID_HDR;

			tuple->sport = 0;
			tuple->dport = 0;

			switch (type) {
			case ICMP_DEST_UNREACH:
			case ICMP_TIME_EXCEEDED:
			case ICMP_PARAMETERPROB:
				tuple->flags |= TUPLE_F_RELATED;
				break;

			case ICMP_ECHOREPLY:
			case ICMP_ECHO:
				if (dir == CT_INGRESS)
					tuple->sport = identifier;
				else
					tuple->dport = identifier;
				/* fall through */
			default:
				action = ACTION_CREATE;
				break;
			}
		}
		break;

	case IPPROTO_TCP:
		if (1) {
			if (ctx_load_bytes(ctx, off + 12, &tcp_flags, 2) < 0)
				return DROP_CT_INVALID_HDR;

			if (unlikely(tcp_flags.value & (TCP_FLAG_RST|TCP_FLAG_FIN)))
				action = ACTION_CLOSE;
			else
				action = ACTION_CREATE;
		}

		if (ipv4_ct_extract_l4_ports(ctx, off, tuple) < 0)
			return DROP_CT_INVALID_HDR;
		break;

	case IPPROTO_UDP:
		if (ipv4_ct_extract_l4_ports(ctx, off, tuple) < 0)
			return DROP_CT_INVALID_HDR;

		action = ACTION_CREATE;
		break;

	default:
		/* Can't handle extension headers yet */
		return DROP_CT_UNKNOWN_PROTO;
	}

	/* Lookup the reverse direction
	 *
	 * This will find an existing flow in the reverse direction.
	 */
#ifndef QUIET_CT
	cilium_dbg3(ctx, DBG_CT_LOOKUP4_1, tuple->saddr, tuple->daddr,
		      (bpf_ntohs(tuple->sport) << 16) | bpf_ntohs(tuple->dport));
	cilium_dbg3(ctx, DBG_CT_LOOKUP4_2, (tuple->nexthdr << 8) | tuple->flags, 0, 0);
#endif
	ret = __ct_lookup(map, ctx, tuple, action, dir, ct_state, is_tcp,
			  tcp_flags, monitor);
	if (ret != CT_NEW) {
		if (likely(ret == CT_ESTABLISHED)) {
			if (unlikely(tuple->flags & TUPLE_F_RELATED))
				ret = CT_RELATED;
			else
				ret = CT_REPLY;
		}
		goto out;
	}

	/* Lookup entry in forward direction */
	if (dir != CT_SERVICE) {
		ipv4_ct_tuple_reverse(tuple);
		ret = __ct_lookup(map, ctx, tuple, action, dir, ct_state,
				  is_tcp, tcp_flags, monitor);
	}
out:
	cilium_dbg(ctx, DBG_CT_VERDICT, ret < 0 ? -ret : ret, ct_state->rev_nat_index);
	if (conn_is_dns(tuple->dport))
		*monitor = MTU;
	return ret;
}

static __always_inline void
ct_update6_backend_id(const void *map, const struct ipv6_ct_tuple *tuple,
		      const struct ct_state *state)
{
	struct ct_entry *entry;

	entry = map_lookup_elem(map, tuple);
	if (!entry)
		return;

	/* See the ct_create4 comments re the rx_bytes hack */
	entry->rx_bytes = state->backend_id;
}

static __always_inline void
ct_update6_rev_nat_index(const void *map, const struct ipv6_ct_tuple *tuple,
			 const struct ct_state *state)
{
	struct ct_entry *entry;

	entry = map_lookup_elem(map, tuple);
	if (!entry)
		return;

	entry->rev_nat_index = state->rev_nat_index;
}

/* Offset must point to IPv6 */
static __always_inline int ct_create6(const void *map_main, const void *map_related,
				      struct ipv6_ct_tuple *tuple,
				      struct __ctx_buff *ctx, const int dir,
				      const struct ct_state *ct_state,
				      bool proxy_redirect)
{
	/* Create entry in original direction */
	struct ct_entry entry = { };
	bool is_tcp = tuple->nexthdr == IPPROTO_TCP;
	union tcp_flags seen_flags = { .value = 0 };

	/* Note if this is a proxy connection so that replies can be redirected
	 * back to the proxy.
	 */
	entry.proxy_redirect = proxy_redirect;

	/* See the ct_create4 comments re the rx_bytes hack */
	if (dir == CT_SERVICE)
		entry.rx_bytes = ct_state->backend_id;

	entry.lb_loopback = ct_state->loopback;
	entry.node_port = ct_state->node_port;
	entry.dsr = ct_state->dsr;
	entry.ifindex = ct_state->ifindex;

	entry.rev_nat_index = ct_state->rev_nat_index;
	seen_flags.value |= is_tcp ? TCP_FLAG_SYN : 0;
	ct_update_timeout(&entry, is_tcp, dir, seen_flags);

	if (dir == CT_INGRESS) {
		entry.rx_packets = 1;
		entry.rx_bytes = ctx_full_len(ctx);
	} else if (dir == CT_EGRESS) {
		entry.tx_packets = 1;
		entry.tx_bytes = ctx_full_len(ctx);
	}

	cilium_dbg3(ctx, DBG_CT_CREATED6, entry.rev_nat_index, ct_state->src_sec_id, 0);

	entry.src_sec_id = ct_state->src_sec_id;
	if (map_update_elem(map_main, tuple, &entry, 0) < 0) {
		send_signal_ct_fill_up(ctx, SIGNAL_PROTO_V6);
		return DROP_CT_CREATE_FAILED;
	}

	if (map_related != NULL) {
		/* Create an ICMPv6 entry to relate errors */
		struct ipv6_ct_tuple icmp_tuple = {
			.nexthdr = IPPROTO_ICMPV6,
			.sport = 0,
			.dport = 0,
			.flags = tuple->flags | TUPLE_F_RELATED,
		};

		entry.seen_non_syn = true; /* For ICMP, there is no SYN. */

		ipv6_addr_copy(&icmp_tuple.daddr, &tuple->daddr);
		ipv6_addr_copy(&icmp_tuple.saddr, &tuple->saddr);

		if (map_update_elem(map_related, &icmp_tuple, &entry, 0) < 0) {
			send_signal_ct_fill_up(ctx, SIGNAL_PROTO_V6);
			return DROP_CT_CREATE_FAILED;
		}
	}
	return 0;
}

static __always_inline void ct_update4_backend_id(const void *map,
						  const struct ipv4_ct_tuple *tuple,
						  const struct ct_state *state)
{
	struct ct_entry *entry;

	entry = map_lookup_elem(map, tuple);
	if (!entry)
		return;

	/* See the ct_create4 comments re the rx_bytes hack */
	entry->rx_bytes = state->backend_id;
}

static __always_inline void
ct_update4_rev_nat_index(const void *map, const struct ipv4_ct_tuple *tuple,
			 const struct ct_state *state)
{
	struct ct_entry *entry;

	entry = map_lookup_elem(map, tuple);
	if (!entry)
		return;

	entry->rev_nat_index = state->rev_nat_index;
}

static __always_inline int ct_create4(const void *map_main,
				      const void *map_related,
				      struct ipv4_ct_tuple *tuple,
				      struct __ctx_buff *ctx, const int dir,
				      const struct ct_state *ct_state,
				      bool proxy_redirect)
{
	/* Create entry in original direction */
	struct ct_entry entry = { };
	bool is_tcp = tuple->nexthdr == IPPROTO_TCP;
	union tcp_flags seen_flags = { .value = 0 };

	/* Note if this is a proxy connection so that replies can be redirected
	 * back to the proxy.
	 */
	entry.proxy_redirect = proxy_redirect;

	entry.lb_loopback = ct_state->loopback;
	entry.node_port = ct_state->node_port;
	entry.dsr = ct_state->dsr;
	entry.ifindex = ct_state->ifindex;

	/* Previously, the rx_bytes field was not used for entries with
	 * the dir=CT_SERVICE (see GH#7060). Therefore, we can safely abuse
	 * this field to save the backend_id.
	 */
	if (dir == CT_SERVICE)
		entry.rx_bytes = ct_state->backend_id;
	entry.rev_nat_index = ct_state->rev_nat_index;
	seen_flags.value |= is_tcp ? TCP_FLAG_SYN : 0;
	ct_update_timeout(&entry, is_tcp, dir, seen_flags);

	if (dir == CT_INGRESS) {
		entry.rx_packets = 1;
		entry.rx_bytes = ctx_full_len(ctx);
	} else if (dir == CT_EGRESS) {
		entry.tx_packets = 1;
		entry.tx_bytes = ctx_full_len(ctx);
	}

#ifdef ENABLE_NAT46
	if (ctx_load_meta(ctx, CB_NAT46_STATE) == NAT64)
		entry.nat46 = dir == CT_EGRESS;
#endif

	cilium_dbg3(ctx, DBG_CT_CREATED4, entry.rev_nat_index,
		    ct_state->src_sec_id, ct_state->addr);

	entry.src_sec_id = ct_state->src_sec_id;
	if (map_update_elem(map_main, tuple, &entry, 0) < 0) {
		send_signal_ct_fill_up(ctx, SIGNAL_PROTO_V4);
		return DROP_CT_CREATE_FAILED;
	}

	if (ct_state->addr && ct_state->loopback) {
		__u8 flags = tuple->flags;
		__be32 saddr, daddr;

		saddr = tuple->saddr;
		daddr = tuple->daddr;

		/* We are looping back into the origin endpoint through a
		 * service, set up a conntrack tuple for the reply to ensure we
		 * do rev NAT before attempting to route the destination
		 * address which will not point back to the right source.
		 */
		tuple->flags = TUPLE_F_IN;
		if (dir == CT_INGRESS) {
			tuple->saddr = ct_state->addr;
			tuple->daddr = ct_state->svc_addr;
		} else {
			tuple->saddr = ct_state->svc_addr;
			tuple->daddr = ct_state->addr;
		}

		if (map_update_elem(map_main, tuple, &entry, 0) < 0) {
			send_signal_ct_fill_up(ctx, SIGNAL_PROTO_V4);
			return DROP_CT_CREATE_FAILED;
		}

		tuple->saddr = saddr;
		tuple->daddr = daddr;
		tuple->flags = flags;
	}

	if (map_related != NULL) {
		/* Create an ICMP entry to relate errors */
		struct ipv4_ct_tuple icmp_tuple = {
			.daddr = tuple->daddr,
			.saddr = tuple->saddr,
			.nexthdr = IPPROTO_ICMP,
			.sport = 0,
			.dport = 0,
			.flags = tuple->flags | TUPLE_F_RELATED,
		};

		entry.seen_non_syn = true; /* For ICMP, there is no SYN. */
		/* Previous map update succeeded, we could delete it in case
		 * the below throws an error, but we might as well just let
		 * it time out.
		 */
		if (map_update_elem(map_related, &icmp_tuple, &entry, 0) < 0) {
			send_signal_ct_fill_up(ctx, SIGNAL_PROTO_V4);
			return DROP_CT_CREATE_FAILED;
		}
	}
	return 0;
}
#else /* !CONNTRACK */
static __always_inline int
ct_lookup6(const void *map __maybe_unused,
	   struct ipv6_ct_tuple *tuple __maybe_unused,
	   struct __ctx_buff *ctx __maybe_unused, int off __maybe_unused,
	   int dir __maybe_unused, struct ct_state *ct_state __maybe_unused,
	   __u32 *monitor __maybe_unused)
{
	return 0;
}

static __always_inline int
ct_lookup4(const void *map __maybe_unused,
	   struct ipv4_ct_tuple *tuple __maybe_unused,
	   struct __ctx_buff *ctx __maybe_unused, int off __maybe_unused,
	   int dir __maybe_unused, struct ct_state *ct_state __maybe_unused,
	   __u32 *monitor __maybe_unused)
{
	return 0;
}

static __always_inline void
ct_update6_backend_id(const void *map __maybe_unused,
		      const struct ipv6_ct_tuple *tuple __maybe_unused,
		      const struct ct_state *state __maybe_unused)
{
}

static __always_inline void
ct_update6_rev_nat_index(const void *map __maybe_unused,
			 const struct ipv6_ct_tuple *tuple __maybe_unused,
			 const struct ct_state *state __maybe_unused)
{
}

static __always_inline int
ct_create6(const void *map_main __maybe_unused,
	   const void *map_related __maybe_unused,
	   struct ipv6_ct_tuple *tuple __maybe_unused,
	   struct __ctx_buff *ctx __maybe_unused, const int dir __maybe_unused,
	   struct ct_state *ct_state __maybe_unused,
	   bool from_proxy __maybe_unused)
{
	return 0;
}

static __always_inline void
ct_update4_backend_id(const void *map __maybe_unused,
		      const struct ipv4_ct_tuple *tuple __maybe_unused,
		      const struct ct_state *state __maybe_unused)
{
}

static __always_inline void
ct_update4_rev_nat_index(const void *map __maybe_unused,
			 const struct ipv4_ct_tuple *tuple __maybe_unused,
			 const struct ct_state *state __maybe_unused)
{
}

static __always_inline int
ct_create4(const void *map_main __maybe_unused,
	   const void *map_related __maybe_unused,
	   struct ipv4_ct_tuple *tuple __maybe_unused,
	   struct __ctx_buff *ctx __maybe_unused, const int dir __maybe_unused,
	   const struct ct_state *ct_state __maybe_unused,
	   bool proxy_redirect __maybe_unused)
{
	return 0;
}

#endif /* CONNTRACK */
#endif /* __LIB_CONNTRACK_H_ */


text:
package trading
import akka.actor.{ Props, Actor }
import akka.actor.ActorLogging
import com.typesafe.config.{ Config, ConfigFactory }
import marketdata.MarketDataTypes.MarketDataType
import marketdata.MarketDataTypes.TickDataType
import marketdata.MarketDataTypes.TradeDataType

import marketdata.{ Tick, Trade, SubscribeListenerRequest }

class TradingActor(val instrument: String, val url_marketdata: String) extends Actor with ActorLogging {

  def receive = {
    case tick: Tick => {
      log.info("trader received " + tick)
    }
    case trade: Trade => {
      log.info("trader received " + trade)
    }
    case x: AnyRef => log.error("unexpected message received " + x)
  }

  override def preStart(): Unit = {
    val selection = context.actorSelection(url_marketdata+"/user/*")
    selection ! SubscribeListenerRequest(self, instrument, Some(List(TickDataType,TradeDataType)))
    ()
  }
}


text:
package slinky.core

import org.scalajs.dom.document
import slinky.core.facade.{React, ReactElement}
import slinky.web.ReactDOM

import org.scalatest.funsuite.AnyFunSuite

class FunctionalComponentTest extends AnyFunSuite {
  test("Can render a functional component") {
    val container = document.createElement("div")
    val component = FunctionalComponent[Int](_.toString)
    ReactDOM.render(component(1), container)

    assert(container.innerHTML == "1")
  }

  test("Re-rendering a memoed component with same props works") {
    val container = document.createElement("div")
    var renderCount = 0
    case class Props(a: Int)
    val component = React.memo(FunctionalComponent[Props] { props =>
      renderCount += 1
      props.a.toString
    })

    val inProps = Props(1)
    ReactDOM.render(component(inProps), container)
    assert(container.innerHTML == "1")
    assert(renderCount == 1)

    ReactDOM.render(component(inProps), container)
    assert(container.innerHTML == "1")
    assert(renderCount == 1)
  }

  test("Re-rendering a memoed component with different props works") {
    val container = document.createElement("div")
    var renderCount = 0
    case class Props(a: Int)
    val component = React.memo(FunctionalComponent[Props] { props =>
      renderCount += 1
      props.a.toString
    })

    val inProps = Props(1)
    ReactDOM.render(component(inProps), container)
    assert(container.innerHTML == "1")
    assert(renderCount == 1)

    ReactDOM.render(component(inProps.copy(a = 2)), container)
    assert(container.innerHTML == "2")
    assert(renderCount == 2)
  }

  test("Re-rendering a memoed component with matching comparison works") {
    val container = document.createElement("div")
    var renderCount = 0
    case class Props(a: Int, ignore: Int)
    val component = React.memo(FunctionalComponent[Props] { props =>
      renderCount += 1
      props.a.toString
    }, (oldProps: Props, newProps: Props) => oldProps.a == newProps.a)

    val inProps = Props(1, 2)
    ReactDOM.render(component(inProps), container)
    assert(container.innerHTML == "1")
    assert(renderCount == 1)

    ReactDOM.render(component(inProps.copy(ignore = 3)), container)
    assert(container.innerHTML == "1")
    assert(renderCount == 1)
  }

  test("Re-rendering a memoed component with non-matching comparison works") {
    val container = document.createElement("div")
    var renderCount = 0
    case class Props(a: Int)
    val component = React.memo(FunctionalComponent[Props] { props =>
      renderCount += 1
      props.a.toString
    }, (oldProps: Props, newProps: Props) => oldProps.a == newProps.a)

    val inProps = Props(1)
    ReactDOM.render(component(inProps), container)
    assert(container.innerHTML == "1")
    assert(renderCount == 1)

    ReactDOM.render(component(inProps.copy(a = 2)), container)
    assert(container.innerHTML == "2")
    assert(renderCount == 2)
  }

  test("Cannot reuse half-built functional component") {
    val component = FunctionalComponent[Int](_.toString)
    val halfBuilt = component(1)
    halfBuilt.withKey("abc"): ReactElement

    assertThrows[IllegalStateException] {
      halfBuilt.withKey("abc2"): ReactElement
    }
  }
}


text:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>LabelSymbolCell</title>
<meta name="date" content="2015-01-13" />
<link rel="stylesheet" type="text/css" href="../../../../stylesheet.css" title="Style" />

 <meta name="generator" content="Adobe RoboHelp 10" />

概述
软件包
 类
树
已过时
索引
帮助

 上一个类   下一个类
    无框架     所有类

摘要: 嵌套 | 字段 | 构造方法 | 方法
详细信息: 字段 | 构造方法 | 方法

com.supermap.android.theme

类 LabelSymbolCell

java.lang.Object
  com.supermap.android.theme.LabelMatrixCell
      com.supermap.android.theme.LabelSymbolCell

所有已实现的接口:

java.io.Serializable

public class LabelSymbolCell

extends LabelMatrixCell

符号类型的矩阵标签元素类。

该类型的对象可作为矩阵标签对象中的一个矩阵标签元素。

另请参见:

序列化表格

字段摘要

 ServerStyle
style

           所使用符号的样式。

 java.lang.String
symbolIDField

           符号 ID 或 记录符号 ID 的字段名称,必设属性。

从类 com.supermap.android.theme.LabelMatrixCell 继承的字段

type

构造方法摘要

LabelSymbolCell()

           构造函数。

方法摘要

从类 java.lang.Object 继承的方法

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

字段详细信息

style

public ServerStyle style

所使用符号的样式。这里 Style 中的符号编码,即符号风格 ID 的设置不起作用,符号风格 ID 由 symbolIDField 指定。

symbolIDField

public java.lang.String symbolIDField

符号 ID 或 记录符号 ID 的字段名称,必设属性。

构造方法详细信息

LabelSymbolCell

public LabelSymbolCell()

构造函数。

概述
软件包
 类
树
已过时
索引
帮助

 上一个类   下一个类
    无框架     所有类

摘要: 嵌套 | 字段 | 构造方法 | 方法
详细信息: 字段 | 构造方法 | 方法


text:
package gce

import (
	"fmt"
	"github.com/golang/glog"
	"golang.org/x/net/context"
	"golang.org/x/oauth2/google"
	compute "google.golang.org/api/compute/v0.beta"
	"google.golang.org/api/storage/v1"
	"k8s.io/kops/pkg/apis/kops"
	"k8s.io/kops/upup/pkg/fi"
	"k8s.io/kubernetes/federation/pkg/dnsprovider"
	"k8s.io/kubernetes/federation/pkg/dnsprovider/providers/google/clouddns"
)

type GCECloud struct {
	Compute *compute.Service
	Storage *storage.Service

	Region  string
	Project string

	labels map[string]string
}

var _ fi.Cloud = &GCECloud{}

func (c *GCECloud) ProviderID() kops.CloudProviderID {
	return kops.CloudProviderGCE
}

func NewGCECloud(region string, project string, labels map[string]string) (*GCECloud, error) {
	c := &GCECloud{Region: region, Project: project}

	ctx := context.Background()

	client, err := google.DefaultClient(ctx, compute.ComputeScope)
	if err != nil {
		return nil, fmt.Errorf("error building google API client: %v", err)
	}
	computeService, err := compute.New(client)
	if err != nil {
		return nil, fmt.Errorf("error building compute API client: %v", err)
	}
	c.Compute = computeService

	storageService, err := storage.New(client)
	if err != nil {
		return nil, fmt.Errorf("error building storage API client: %v", err)
	}
	c.Storage = storageService

	c.labels = labels

	return c, nil
}

func (c *GCECloud) DNS() (dnsprovider.Interface, error) {
	provider, err := clouddns.CreateInterface(c.Project, nil)
	if err != nil {
		return nil, fmt.Errorf("Error building (k8s) DNS provider: %v", err)
	}
	return provider, nil
}

func (c *GCECloud) FindVPCInfo(id string) (*fi.VPCInfo, error) {
	glog.Warningf("FindVPCInfo not (yet) implemented on GCE")
	return nil, nil
}

func (c *GCECloud) Labels() map[string]string {
	// Defensive copy
	tags := make(map[string]string)
	for k, v := range c.labels {
		tags[k] = v
	}
	return tags
}

func (c *GCECloud) WaitForOp(op *compute.Operation) error {
	return WaitForOp(c.Compute, op)
}

func (c *GCECloud) GetApiIngressStatus(cluster *kops.Cluster) ([]kops.ApiIngressStatus, error) {
	var ingresses []kops.ApiIngressStatus

	// Note that this must match GCEModelContext::NameForForwardingRule
	name := SafeObjectName("api", cluster.ObjectMeta.Name)

	glog.V(2).Infof("Querying GCE to find ForwardingRules for API (%q)", name)
	forwardingRule, err := c.Compute.ForwardingRules.Get(c.Project, c.Region, name).Do()
	if err != nil {
		if !IsNotFound(err) {
			forwardingRule = nil
		} else {
			return nil, fmt.Errorf("error getting ForwardingRule %q: %v", name, err)
		}
	}

	if forwardingRule != nil {
		if forwardingRule.IPAddress == "" {
			return nil, fmt.Errorf("Found forward rule %q, but it did not have an IPAddress", name)
		}

		ingresses = append(ingresses, kops.ApiIngressStatus{
			IP: forwardingRule.IPAddress,
		})
	}

	return ingresses, nil
}


text:
FactoryBot.define do
  factory :farm_event do
    start_time { Date.yesterday - [*(1..5)].sample.days }
    end_time   { Date.today + 1.minute + ([*(1..5)].sample).days }
    time_unit  { FarmEvent::UNITS_OF_TIME.sample }
    repeat { [*(1..5)].sample }
    # device
    after(:build) do |s|
      s.executable ||= FakeSequence.create(device: s.device)
      s.device ||= s.executable.try(:device)
    end
  end
end


text:
namespace boost
{
  namespace math
  {
    namespace tools
    {
      // If either T1 or T2 is an integer type,
      // pretend it was a double (for the purposes of further analysis).
      // Then pick the wider of the two floating-point types
      // as the actual signature to forward to.
      // For example:
      // foo(int, short) -> double foo(double, double);
      // foo(int, float) -> double foo(double, double);
      // Note: NOT float foo(float, float)
      // foo(int, double) -> foo(double, double);
      // foo(double, float) -> double foo(double, double);
      // foo(double, float) -> double foo(double, double);
      // foo(any-int-or-float-type, long double) -> foo(long double, long double);
      // but ONLY float foo(float, float) is unchanged.
      // So the only way to get an entirely float version is to call foo(1.F, 2.F),
      // But since most (all?) the math functions convert to double internally,
      // probably there would not be the hoped-for gain by using float here.

      // This follows the C-compatible conversion rules of pow, etc
      // where pow(int, float) is converted to pow(double, double).

      template <class T>
      struct promote_arg
      { // If T is integral type, then promote to double.
        using type = typename std::conditional<std::is_integral<T>::value, double, T>::type;
      };
      // These full specialisations reduce std::conditional usage and speed up
      // compilation:
      template <> struct promote_arg<float> { using type = float; };
      template <> struct promote_arg<double>{ using type = double; };
      template <> struct promote_arg<long double> { using type = long double; };
      template <> struct promote_arg<int> {  using type = double; };

      template <class T1, class T2>
      struct promote_args_2
      { // Promote, if necessary, & pick the wider of the two floating-point types.
        // for both parameter types, if integral promote to double.
        using T1P = typename promote_arg<T1>::type; // T1 perhaps promoted.
        using T2P = typename promote_arg<T2>::type; // T2 perhaps promoted.

        using type = typename std::conditional<
          std::is_floating_point<T1P>::value && std::is_floating_point<T2P>::value, // both T1P and T2P are floating-point?
#ifdef BOOST_MATH_USE_FLOAT128
           typename std::conditional<std::is_same<__float128, T1P>::value || std::is_same<__float128, T2P>::value, // either long double?
            __float128,
#endif
             typename std::conditional<std::is_same<long double, T1P>::value || std::is_same<long double, T2P>::value, // either long double?
               long double, // then result type is long double.
               typename std::conditional<std::is_same<double, T1P>::value || std::is_same<double, T2P>::value, // either double?
                  double, // result type is double.
                  float // else result type is float.
             >::type
#ifdef BOOST_MATH_USE_FLOAT128
             >::type
#endif
             >::type,
          // else one or the other is a user-defined type:
          typename std::conditional<!std::is_floating_point<T2P>::value && std::is_convertible<T1P, T2P>::value, T2P, T1P>::type>::type;
      }; // promote_arg2
      // These full specialisations reduce std::conditional usage and speed up
      // compilation:
      template <> struct promote_args_2<float, float> { using type = float; };
      template <> struct promote_args_2<double, double>{ using type = double; };
      template <> struct promote_args_2<long double, long double> { using type = long double; };
      template <> struct promote_args_2<int, int> {  using type = double; };
      template <> struct promote_args_2<int, float> {  using type = double; };
      template <> struct promote_args_2<float, int> {  using type = double; };
      template <> struct promote_args_2<int, double> {  using type = double; };
      template <> struct promote_args_2<double, int> {  using type = double; };
      template <> struct promote_args_2<int, long double> {  using type = long double; };
      template <> struct promote_args_2<long double, int> {  using type = long double; };
      template <> struct promote_args_2<float, double> {  using type = double; };
      template <> struct promote_args_2<double, float> {  using type = double; };
      template <> struct promote_args_2<float, long double> {  using type = long double; };
      template <> struct promote_args_2<long double, float> {  using type = long double; };
      template <> struct promote_args_2<double, long double> {  using type = long double; };
      template <> struct promote_args_2<long double, double> {  using type = long double; };

      template <class T1, class T2=float, class T3=float, class T4=float, class T5=float, class T6=float>
      struct promote_args
      {
         using type = typename promote_args_2<
            typename std::remove_cv<T1>::type,
            typename promote_args_2<
               typename std::remove_cv<T2>::type,
               typename promote_args_2<
                  typename std::remove_cv<T3>::type,
                  typename promote_args_2<
                     typename std::remove_cv<T4>::type,
                     typename promote_args_2<
                        typename std::remove_cv<T5>::type, typename std::remove_cv<T6>::type
                     >::type
                  >::type
               >::type
            >::type
         >::type;

#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
         //
         // Guard against use of long double if it's not supported:
         //
         BOOST_STATIC_ASSERT_MSG((0 == std::is_same<type, long double>::value), "Sorry, but this platform does not have sufficient long double support for the special functions to be reliably implemented.");
#endif
      };

      //
      // This struct is the same as above, but has no static assert on long double usage,
      // it should be used only on functions that can be implemented for long double
      // even when std lib support is missing or broken for that type.
      //
      template <class T1, class T2=float, class T3=float, class T4=float, class T5=float, class T6=float>
      struct promote_args_permissive
      {
         using type = typename promote_args_2<
            typename std::remove_cv<T1>::type,
            typename promote_args_2<
               typename std::remove_cv<T2>::type,
               typename promote_args_2<
                  typename std::remove_cv<T3>::type,
                  typename promote_args_2<
                     typename std::remove_cv<T4>::type,
                     typename promote_args_2<
                        typename std::remove_cv<T5>::type, typename std::remove_cv<T6>::type
                     >::type
                  >::type
               >::type
            >::type
         >::type;
      };

    } // namespace tools
  } // namespace math
} // namespace boost

#endif // BOOST_MATH_PROMOTION_HPP


text:
"""Ensure the expected functioning of ``memote.suite.io.config``."""

from __future__ import absolute_import

import json
from builtins import zip
from os.path import dirname, join

import pytest
from importlib_resources import open_text
from jsonschema import Draft4Validator, ValidationError
from numpy import isclose

from memote.experimental.config import ExperimentConfiguration

DATA_PATH = join(dirname(__file__), "data")

def test_configuration_schema():
    """Validate the schema itself against its specification."""
    with open_text(
        "memote.experimental.schemata", "configuration.json", encoding="utf-8"
    ) as file_handle:
        schema = json.load(file_handle)
    Draft4Validator.check_schema(schema)  # Will raise an exception if invalid.

@pytest.mark.parametrize(
    "filename",
    [
        pytest.param("empty.yml", marks=pytest.mark.raises(exception=ValidationError)),
        pytest.param(
            "invalid.yml", marks=pytest.mark.raises(exception=ValidationError)
        ),
        "valid.yml",
        "medium_only.yml",
    ],
)
def test_configuration(filename):
    config = ExperimentConfiguration(join(DATA_PATH, filename))
    config.validate()

@pytest.mark.parametrize(
    "filename, model, media, growth",
    [
        (
            "medium_only.yml",
            "textbook",
            [u"glucose", u"m9_fructose", u"pyruvate"],
            [0.874, 0.416, 0.291],
        )
    ],
    indirect=["model"],
)
def test_load_medium(filename, model, media, growth):
    config = ExperimentConfiguration(join(DATA_PATH, filename))
    config.validate()
    config.load_medium(model)
    for medium_id, value in zip(media, growth):
        assert medium_id in config.media
        with model:
            config.media[medium_id].apply(model)
            assert isclose(model.slim_optimize(), value, atol=1e-03)

@pytest.mark.parametrize(
    "filename, model, experiment",
    [(u"essentiality_only.yml", u"textbook", u"core_deletion")],
    indirect=["model"],
)
def test_load_essentiality(filename, model, experiment):
    config = ExperimentConfiguration(join(DATA_PATH, filename))
    config.validate()
    config.load_medium(model)
    config.load_essentiality(model)
    exp = config.essentiality[experiment]
    expected = exp.data
    expected.sort_values("gene", inplace=True)
    test = exp.evaluate(model)
    test.sort_values("gene", inplace=True)
    assert (test["essential"].values == expected["essential"].values).all()

@pytest.mark.parametrize(
    "filename, model, experiment",
    [(u"growth.yml", u"textbook", u"core")],
    indirect=["model"],
)
def test_load_growth(filename, model, experiment):
    config = ExperimentConfiguration(join(DATA_PATH, filename))
    config.validate()
    config.load_medium(model)
    config.load_growth(model)
    exp = config.growth[experiment]
    expected = exp.data
    expected.sort_values("exchange", inplace=True)
    test = exp.evaluate(model)
    test.sort_values("exchange", inplace=True)
    assert (test["growth"].values == expected["growth"].values).all()


text:
package org.apache.commons.jcs3.utils.discovery;

/**
 * This class periodically check the lastHeardFrom time on the services.
 *

 * If they exceed the configurable limit, it removes them from the set.
 *

 * @deprecated Functionality moved to UDPDiscoveryService
 */
@Deprecated
public class UDPCleanupRunner
    implements Runnable
{
    /** UDP discovery service */
    private final UDPDiscoveryService discoveryService;

    /**
     * @param service UDPDiscoveryService
     */
    public UDPCleanupRunner( final UDPDiscoveryService service )
    {
        this.discoveryService = service;
    }

    /**
     * This goes through the list of services and removes those that we haven't heard from in longer
     * than the max idle time.
     *

     * @see Runnable#run()
     */
    @Override
    public void run()
    {
        discoveryService.cleanup();
    }
}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using WebAPI.Boilerplate.BusinessService.Interface;
using WebAPI.Boilerplate.Logger;

namespace WebAPI.Boilerplate.Api.Controllers
{
    public class EmployeesController : ApiController
    {
        private readonly IEmployeeService employeeService;
        private readonly BaseLogger baseLogger;

        //private readonly BaseLogger baseLogger;

        public EmployeesController(IEmployeeService employeeService, BaseLogger logger)
        {

            this.employeeService = employeeService;
            this.baseLogger = logger;
        }

        // GET api/employee
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }

        // GET api/employee/5
        public Model.Employee Get(int id)
        {
            this.baseLogger.Logger.Debug("Test from web api controller");
            return (employeeService.GetEmployee(id));
        }

        // POST api/employee
        public void Post([FromBody]string value)
        {
        }

        // PUT api/employee/5
        public void Put(int id, [FromBody]string value)
        {
        }

        // DELETE api/employee/5
        public void Delete(int id)
        {
        }
    }
}


text:
namespace DiscUtils.Vmdk
{
    internal class CommonSparseExtentHeader
    {
        public long Capacity;
        public long GdOffset;
        public long GrainSize;
        public uint MagicNumber;
        public uint NumGTEsPerGT;
        public uint Version;
    }
}


text:
---
uid: SolidEdgeFramework.InterpartLink.IsFrozen(System.Boolean@)
summary:
remarks:
---


text:
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2008-2017 FIRST. 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 the root directory of */
/* the project.                                                               */
/*----------------------------------------------------------------------------*/

#include "AnalogGyro.h"

#include <climits>

#include <HAL/AnalogGyro.h>
#include <HAL/Errors.h>
#include <HAL/HAL.h>

#include "AnalogInput.h"
#include "LiveWindow/LiveWindow.h"
#include "Timer.h"
#include "WPIErrors.h"

using namespace frc;

const int AnalogGyro::kOversampleBits;
const int AnalogGyro::kAverageBits;
constexpr double AnalogGyro::kSamplesPerSecond;
constexpr double AnalogGyro::kCalibrationSampleTime;
constexpr double AnalogGyro::kDefaultVoltsPerDegreePerSecond;

/**
 * Gyro constructor using the Analog Input channel number.
 *
 * @param channel The analog channel the gyro is connected to. Gyros can only
 *                be used on on-board Analog Inputs 0-1.
 */
AnalogGyro::AnalogGyro(int channel)
    : AnalogGyro(std::make_shared<AnalogInput>(channel)) {}

/**
 * Gyro constructor with a precreated AnalogInput object.
 *
 * Use this constructor when the analog channel needs to be shared.
 * This object will not clean up the AnalogInput object when using this
 * constructor.
 *
 * Gyros can only be used on on-board channels 0-1.
 *
 * @param channel A pointer to the AnalogInput object that the gyro is
 *                connected to.
 */
AnalogGyro::AnalogGyro(AnalogInput* channel)
    : AnalogGyro(
          std::shared_ptr<AnalogInput>(channel, NullDeleter<AnalogInput>())) {}

/**
 * Gyro constructor with a precreated AnalogInput object.
 *
 * Use this constructor when the analog channel needs to be shared.
 * This object will not clean up the AnalogInput object when using this
 * constructor.
 *
 * @param channel A pointer to the AnalogInput object that the gyro is
 *                connected to.
 */
AnalogGyro::AnalogGyro(std::shared_ptr<AnalogInput> channel)
    : m_analog(channel) {
  if (channel == nullptr) {
    wpi_setWPIError(NullParameter);
  } else {
    InitGyro();
    Calibrate();
  }
}

/**
 * Gyro constructor using the Analog Input channel number with parameters for
 * presetting the center and offset values. Bypasses calibration.
 *
 * @param channel The analog channel the gyro is connected to. Gyros can only
 *                be used on on-board Analog Inputs 0-1.
 * @param center  Preset uncalibrated value to use as the accumulator center
 *                value.
 * @param offset  Preset uncalibrated value to use as the gyro offset.
 */
AnalogGyro::AnalogGyro(int channel, int center, double offset) {
  m_analog = std::make_shared<AnalogInput>(channel);
  InitGyro();
  int32_t status = 0;
  HAL_SetAnalogGyroParameters(m_gyroHandle, kDefaultVoltsPerDegreePerSecond,
                              offset, center, &status);
  if (status != 0) {
    wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
    m_gyroHandle = HAL_kInvalidHandle;
    return;
  }
  Reset();
}

/**
 * Gyro constructor with a precreated AnalogInput object and calibrated
 * parameters.
 *
 * Use this constructor when the analog channel needs to be shared.
 * This object will not clean up the AnalogInput object when using this
 * constructor.
 *
 * @param channel A pointer to the AnalogInput object that the gyro is
 *                connected to.
 */
AnalogGyro::AnalogGyro(std::shared_ptr<AnalogInput> channel, int center,
                       double offset)
    : m_analog(channel) {
  if (channel == nullptr) {
    wpi_setWPIError(NullParameter);
  } else {
    InitGyro();
    int32_t status = 0;
    HAL_SetAnalogGyroParameters(m_gyroHandle, kDefaultVoltsPerDegreePerSecond,
                                offset, center, &status);
    if (status != 0) {
      wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
      m_gyroHandle = HAL_kInvalidHandle;
      return;
    }
    Reset();
  }
}

/**
 * AnalogGyro Destructor
 *
 */
AnalogGyro::~AnalogGyro() { HAL_FreeAnalogGyro(m_gyroHandle); }

/**
 * Reset the gyro.
 *
 * Resets the gyro to a heading of zero. This can be used if there is
 * significant drift in the gyro and it needs to be recalibrated after it has
 * been running.
 */
void AnalogGyro::Reset() {
  if (StatusIsFatal()) return;
  int32_t status = 0;
  HAL_ResetAnalogGyro(m_gyroHandle, &status);
  wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}

/**
 * Initialize the gyro.  Calibration is handled by Calibrate().
 */
void AnalogGyro::InitGyro() {
  if (StatusIsFatal()) return;
  if (m_gyroHandle == HAL_kInvalidHandle) {
    int32_t status = 0;
    m_gyroHandle = HAL_InitializeAnalogGyro(m_analog->m_port, &status);
    if (status == PARAMETER_OUT_OF_RANGE) {
      wpi_setWPIErrorWithContext(ParameterOutOfRange,
                                 " channel (must be accumulator channel)");
      m_analog = nullptr;
      m_gyroHandle = HAL_kInvalidHandle;
      return;
    }
    if (status != 0) {
      wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
      m_analog = nullptr;
      m_gyroHandle = HAL_kInvalidHandle;
      return;
    }
  }

  int32_t status = 0;
  HAL_SetupAnalogGyro(m_gyroHandle, &status);
  if (status != 0) {
    wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
    m_analog = nullptr;
    m_gyroHandle = HAL_kInvalidHandle;
    return;
  }

  HAL_Report(HALUsageReporting::kResourceType_Gyro, m_analog->GetChannel());
  LiveWindow::GetInstance()->AddSensor("AnalogGyro", m_analog->GetChannel(),
                                       this);
}

void AnalogGyro::Calibrate() {
  if (StatusIsFatal()) return;
  int32_t status = 0;
  HAL_CalibrateAnalogGyro(m_gyroHandle, &status);
  wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}

/**
 * Return the actual angle in degrees that the robot is currently facing.
 *
 * The angle is based on the current accumulator value corrected by the
 * oversampling rate, the gyro type and the A/D calibration values.
 * The angle is continuous, that is it will continue from 360->361 degrees. This
 * allows algorithms that wouldn't want to see a discontinuity in the gyro
 * output as it sweeps from 360 to 0 on the second time around.
 *
 * @return the current heading of the robot in degrees. This heading is based on
 *         integration of the returned rate from the gyro.
 */
double AnalogGyro::GetAngle() const {
  if (StatusIsFatal()) return 0.0;
  int32_t status = 0;
  double value = HAL_GetAnalogGyroAngle(m_gyroHandle, &status);
  wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
  return value;
}

/**
 * Return the rate of rotation of the gyro
 *
 * The rate is based on the most recent reading of the gyro analog value
 *
 * @return the current rate in degrees per second
 */
double AnalogGyro::GetRate() const {
  if (StatusIsFatal()) return 0.0;
  int32_t status = 0;
  double value = HAL_GetAnalogGyroRate(m_gyroHandle, &status);
  wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
  return value;
}

/**
 * Return the gyro offset value. If run after calibration,
 * the offset value can be used as a preset later.
 *
 * @return the current offset value
 */
double AnalogGyro::GetOffset() const {
  if (StatusIsFatal()) return 0.0;
  int32_t status = 0;
  double value = HAL_GetAnalogGyroOffset(m_gyroHandle, &status);
  wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
  return value;
}

/**
 * Return the gyro center value. If run after calibration,
 * the center value can be used as a preset later.
 *
 * @return the current center value
 */
int AnalogGyro::GetCenter() const {
  if (StatusIsFatal()) return 0;
  int32_t status = 0;
  int value = HAL_GetAnalogGyroCenter(m_gyroHandle, &status);
  wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
  return value;
}

/**
 * Set the gyro sensitivity.
 *
 * This takes the number of volts/degree/second sensitivity of the gyro and uses
 * it in subsequent calculations to allow the code to work with multiple gyros.
 * This value is typically found in the gyro datasheet.
 *
 * @param voltsPerDegreePerSecond The sensitivity in Volts/degree/second
 */
void AnalogGyro::SetSensitivity(double voltsPerDegreePerSecond) {
  int32_t status = 0;
  HAL_SetAnalogGyroVoltsPerDegreePerSecond(m_gyroHandle,
                                           voltsPerDegreePerSecond, &status);
  wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}

/**
 * Set the size of the neutral zone.
 *
 * Any voltage from the gyro less than this amount from the center is
 * considered stationary.  Setting a deadband will decrease the amount of drift
 * when the gyro isn't rotating, but will make it less accurate.
 *
 * @param volts The size of the deadband in volts
 */
void AnalogGyro::SetDeadband(double volts) {
  if (StatusIsFatal()) return;
  int32_t status = 0;
  HAL_SetAnalogGyroDeadband(m_gyroHandle, volts, &status);
  wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}