text:
require "rails_helper"

describe Dorsale::Flyboy::TasksController, type: :controller do
  routes { Dorsale::Engine.routes }

  let(:user) { create(:user) }

  before(:each) { sign_in(user) }

  let!(:task) {
    create(:flyboy_task, done: false)
  }

  let(:valid_attributes) {
    {
      :name => "New Task",
      :term => Date.current,
    }
  }

  describe "#complete" do
    before(:each) do
      request.env["HTTP_REFERER"] = "where_i_came_from"
    end

    it "should mark the task as done" do
      patch :complete, params: {id: task.id}
      expect(task.reload.done).to be true
    end

    it "should set progress to 100" do
      patch :complete, params: {id: task.id}
      expect(task.reload.progress).to eq(100)
    end

    it "should add a task_comment" do
      count = task.comments.count
      patch :complete, params: {id: task.id}
      expect(task.reload.comments.count).to eq(count+1)
      expect(task.comments.last.progress).to eq(100)
    end

    it "should redirect to the referer page" do
      patch :complete, params: {id: task.id}
      expect(response).to redirect_to "where_i_came_from"
    end
  end

  describe "GET index" do
    context "when applying filter" do
      before do
        Dorsale::Flyboy::Task.destroy_all
        @task1 = create(:flyboy_task, done: true)
        @task2 = create(:flyboy_task, done: false)
      end

      it "should display both when not filtered" do
        get :index
        expect(assigns(:tasks).to_a.sort).to eq [@task1, @task2].sort
      end

      it "should filter by status closed" do
        cookies["filters"] = {"fb_state" => "done"}.to_json
        get :index
        expect(assigns(:tasks).to_a).to eq [@task1]
      end

      it "should filter by status opened" do
        cookies["filters"] = {"fb_state" => "undone"}.to_json
        get :index
        expect(assigns(:tasks).to_a).to eq [@task2]
      end

      it "should filter by tags" do
        task1 = create(:flyboy_task, tag_list: "abc")
        task2 = create(:flyboy_task, tag_list: "xyz")
        cookies["filters"] = {fb_tags: ["abc"]}.to_json
        get :index
        expect(assigns(:tasks)).to eq [task1]
      end
    end

    context "when sorting" do
      before do
        Dorsale::Flyboy::Task.destroy_all
        @corporation1 = create(:customer_vault_corporation, name: "Abc")
        @corporation2 = create(:customer_vault_corporation, name: "dEF")
        @corporation3 = create(:customer_vault_corporation, name: "xyz")

        @task1 = create(:flyboy_task,
          :taskable      => @corporation1,
          :name          => "Abc",
          :progress      => 100,
          :term          => "21/12/2012",
          :reminder_type => "custom",
          :reminder_date => "21/12/2012",
          :tag_list      => "aaa",
        )

        @task2 = create(:flyboy_task,
          :taskable      => @corporation2,
          :name          => "dEF",
          :progress      => 0,
          :term          => "23/12/2012",
          :reminder_type => "custom",
          :reminder_date => "23/12/2012",
          :tag_list      => "bbb",
        )

        @task3 = create(:flyboy_task,
          :taskable      => @corporation3,
          :name          => "xyz",
          :progress      => 35,
          :term          => "22/12/2012",
          :reminder_type => "custom",
          :reminder_date => "22/12/2012",
          :tag_list      => "",
        )
      end

      it "sorting by taskable asc" do
        get :index, params: {sort: "taskable"}
        expect(assigns(:tasks).to_a).to eq [@task1, @task2, @task3]
      end

      it "sorting by taskable desc" do
        get :index, params: {sort: "-taskable"}
        expect(assigns(:tasks).to_a).to eq [@task3, @task2, @task1]
      end

      it "sorting by name asc" do
        get :index, params: {sort: "name"}
        expect(assigns(:tasks).to_a).to eq [@task1, @task2, @task3]
      end

      it "sorting by name desc" do
        get :index, params: {sort: "-name"}
        expect(assigns(:tasks).to_a).to eq [@task3, @task2, @task1]
      end

      it "sorting by progress asc" do
        get :index, params: {sort: "progress"}
        expect(assigns(:tasks).to_a).to eq [@task2, @task3, @task1]
      end

      it "sorting by progress desc" do
        get :index, params: {sort: "-progress"}
        expect(assigns(:tasks).to_a).to eq [@task1, @task3, @task2]
      end

      it "sorting by term asc" do
        get :index, params: {sort: "term"}
        expect(assigns(:tasks).to_a).to eq [@task1, @task3, @task2]
      end

      it "sorting by term desc" do
        get :index, params: {sort: "-term"}
        expect(assigns(:tasks).to_a).to eq [@task2, @task3, @task1]
      end

      it "sorting by tags asc" do
        get :index, params: {sort: "tags"}
        expect(assigns(:tasks).to_a).to eq [@task1, @task2, @task3]
      end

      it "sorting by tags desc" do
        get :index, params: {sort: "-tags"}
        expect(assigns(:tasks).to_a).to eq [@task3, @task2, @task1]
      end
    end
  end

  describe "GET show" do
    it "assigns the requested task as @task" do
      get :show, params: {:id => task.to_param}
      expect(assigns(:task)).to eq(task)
    end
  end

  describe "GET edit" do
    it "assigns the requested task as @task" do
      get :edit, params: {:id => task.to_param}
      expect(assigns(:task)).to eq(task)
    end
  end

  describe "POST create" do
    describe "with valid params" do
      it "creates a new Task" do
        expect {
          post :create, params: {:task => valid_attributes}
        }.to change(Dorsale::Flyboy::Task, :count).by(1)
      end

      it "assigns a newly created task as @task" do
        post :create, params: {:task => valid_attributes}
        expect(assigns(:task)).to be_a(Dorsale::Flyboy::Task)
        expect(assigns(:task)).to be_persisted
      end

      it "redirects to the created task" do
        post :create, params: {:task => valid_attributes}
        expect(response).to redirect_to Dorsale::Flyboy::Task.last_created
      end

      it "should send a mail to the owner" do
        owner = create(:user)
        ActionMailer::Base.deliveries.clear
        post :create, params: {:task => valid_attributes.merge(owner_id: owner.id)}
        expect(ActionMailer::Base.deliveries.count).to eq 1
        email = ActionMailer::Base.deliveries.last
        expect(email.to).to include owner.email
        expect(email.subject).to include "New Task"
        expect(email.body).to include @user.to_s
        expect(email.body).to include "http://"
      end

      it "should not send a mail if there is no owner" do
        ActionMailer::Base.deliveries.clear
        post :create, params: {:task => valid_attributes}
        expect(ActionMailer::Base.deliveries.count).to eq 0
      end

      it "should not send a mail if the author is the owner" do
        ActionMailer::Base.deliveries.clear
        post :create, params: {:task => valid_attributes}
        expect(ActionMailer::Base.deliveries.count).to eq 0
      end
    end
  end

  describe "PUT update" do
    let!(:task) { create(:flyboy_task) }

    describe "with valid params" do
      it "assigns the requested task as @task" do
        patch :update, params: {id: task, task: valid_attributes}
        expect(assigns(:task)).to eq(task)
      end

      it "redirects to the task" do
        patch :update, params: {id: task, task: valid_attributes}
        expect(response).to redirect_to(task)
      end

      it "should create term changed comment" do
        valid_attributes[:term] = task.term - 3.days

        expect {
          patch :update, params: {id: task, task: valid_attributes}
        }.to change(Dorsale::Flyboy::TaskComment, :count).by(1)
      end
    end

    describe "with invalid params" do
      it "assigns the task as @task" do
        patch :update, params: {id: task, task: {name: nil}}
        expect(assigns(:task)).to eq(task)
      end
    end
  end

  describe "DELETE destroy" do
    it "destroys the requested task" do
      task = create(:flyboy_task)
      expect {
        delete :destroy, params: {:id => task.to_param}
      }.to change(Dorsale::Flyboy::Task, :count).by(-1)
    end

    it "redirects to the tasks list" do
      task = create(:flyboy_task)
      delete :destroy, params: {:id => task.to_param}
      expect(response).to redirect_to(flyboy_tasks_path)
    end
  end

  describe "snooze" do
    it "should redirect to the task list to refresh it" do
      task = create(:flyboy_task, term: 3.days.ago)
      patch :snooze, params: {:id => task.to_param}
      expect(response).to redirect_to(task)
    end

    it "is expected to create a task comment" do
      task = create(:flyboy_task, term: 3.days.ago)
      expect {
        patch :snooze, params: {:id => task.to_param}
      }.to change(Dorsale::Flyboy::TaskComment, :count).by(1)
    end
  end

  describe "summary" do
    let(:summary_user) { create :user }

    before(:each) do
      Dorsale::Flyboy::Task.destroy_all
      sign_in summary_user

      Timecop.freeze "2016-03-09 15:00:00"
      @delayed_task        = create(:flyboy_task, term: Date.yesterday)           # tuesday
      @today_task          = create(:flyboy_task, term: Date.current)             # thursday - today
      @tomorrow_task       = create(:flyboy_task, term: Date.tomorrow)            # wednesday
      @this_week_task      = create(:flyboy_task, term: Date.parse("2016-03-12")) # sunday
      @next_week_task      = create(:flyboy_task, term: Date.parse("2016-03-14")) # monday next week
      @next_next_week_task = create(:flyboy_task, term: Date.parse("2016-03-22")) # tuesday 2 weeks
    end

    it "should not assign tasks when owner is an other person" do
      other_user = create(:user)
      Dorsale::Flyboy::Task.update_all(owner_id: other_user.id)

      Timecop.freeze "2016-03-09 15:00:00"
      controller.setup_tasks_summary
      expect(assigns(:delayed_tasks)).to        eq []
      expect(assigns(:today_tasks)).to          eq []
      expect(assigns(:tomorrow_tasks)).to       eq []
      expect(assigns(:this_week_tasks)).to      eq []
      expect(assigns(:next_week_tasks)).to      eq []
      expect(assigns(:next_next_week_tasks)).to eq []
    end

    it "should assign tasks when owner is nil" do
      Dorsale::Flyboy::Task.update_all(owner_id: nil)

      Timecop.freeze "2016-03-09 15:00:00"
      controller.setup_tasks_summary
      expect(assigns(:delayed_tasks)).to        eq [@delayed_task]
      expect(assigns(:today_tasks)).to          eq [@today_task]
      expect(assigns(:tomorrow_tasks)).to       eq [@tomorrow_task]
      expect(assigns(:this_week_tasks)).to      eq [@this_week_task]
      expect(assigns(:next_week_tasks)).to      eq [@next_week_task]
      expect(assigns(:next_next_week_tasks)).to eq [@next_next_week_task]
    end

    it "should assign tasks when owner is me" do
      Dorsale::Flyboy::Task.update_all(owner_id: summary_user.id)

      Timecop.freeze "2016-03-09 15:00:00"
      controller.setup_tasks_summary
      expect(assigns(:delayed_tasks)).to        eq [@delayed_task]
      expect(assigns(:today_tasks)).to          eq [@today_task]
      expect(assigns(:tomorrow_tasks)).to       eq [@tomorrow_task]
      expect(assigns(:this_week_tasks)).to      eq [@this_week_task]
      expect(assigns(:next_week_tasks)).to      eq [@next_week_task]
      expect(assigns(:next_next_week_tasks)).to eq [@next_next_week_task]
    end
  end # describe summary
end


text:
title: Strong encryption for small payloads on Arduino
author: Michael Kwaśnicki
date: 2018-03-05
tags: [Arduino, Encryption]
photos: rc4d.svg
---

Most time, the wireless communication between embedded devices like the Arduino happens in plain text. While block ciphers like AES are too bulky in terms of speed, payload and object code size, stream ciphers like RC4 do not offer a high level of security through the lack of diffusion. In this post I will describe a new method to use a modified stream cipher that offers diffusion and also works with no overhead on small payloads, that are common in such devices.

## Objective ##

In some of my projects I want to use wireless communication between multiple embedded devices. Some applications like smart-home might contain sensitive data or might be susceptible to attackers that might gain control over every device. So I would like to encrypt the messages in a simple but secure way. Currently AES is state of the art but is not simple and comes along with some constraints. Yet it offers a high degree of diffusion. RC4 on the other side is very simple and fast but does not offer the same level of security. For example, there is no diffusion at all.

What I want is an encryption that is effective and offers a high diffusion like AES but works on payloads of arbitrary length without extra cost and ais simple and fast like RC4. But in my research I found no cipher that offers everything I want.

What is this diffusion anyway?

[Diffusion][wiki_diffusion] describes how the output ciphertext differs if only one bit/byte in the input plaintext changes. So the change might affect only this one bit/byte or also its neighbors, its containing block or the entire ciphertext. The higher the diffusion the more unpredictable is the ciphertext.

### Why not AES ###

The [Advanced Encryption Standard][wiki_AES] (AES) is a block cipher. That means that the cipher operates on a block of plaintext with a fixed size. For AES, that is 128 bits or 16 bytes. AES has three sub types where the key length is 128, 192 or 256 bits but the block size stays the same. AES scatters the plaintext within that block and scrambles it in such a way that changing only 1 bit results in a completely different resulting block of ciphertext.

    {% asset_img aes.svg %}

A small change to the plaintext results in a completely different ciphertext in AES.

For data whose length is not a multiple of a block, the last block needs to be padded. The padded block needs to be transferred completely along with the information how many bytes have been padded. So there is an overhead that needs to be transferred in order to obtain the original plaintext. Also the algorithm is so complex that it takes up much of the scarce space on the embedded device and also takes more time to process the data.

### Why not RC4 ###

[Rivest Cipher 4][wiki_RC4] (RC4) is a stream cipher. This category of ciphers is intended for use with streams of arbitrary length. A stream cipher generates a pseudo random stream from a key of 40 – 2048 bits, that is XOR'ed with the plaintext. This is simple and fast but also has its flaws. There is no diffusion. Changes to the plaintext are local. So when using the same key all over again, the content will be successfully attacked on the long run.

    {% asset_img rc4.svg %}

A small change to the plaintext results in a change to the same bit in the ciphertext in RC4.

But changing the key after every message bears dangers as the sender and receiver have to agree for the key to use. Getting out of sync leads to unreadable messages. Beside that RC4 is considered broken and was removed from all official recommendations. Yet it is so easy to implement and so fast that it is perfectly suitable for embedded devices.

## A new hope for RC4 ##

Block ciphers know different [operation modes][wiki_modes] in order to prevent attacks on long payloads. There are also operation modes that allow block ciphers to be used like a stream cipher. The block cipher generates just a key stream. When looking at the [Electronic Codebook][wiki_modes_ECB] (ECB) operation mode, we see analogies to RC4. Each block of plaintext is being encrypted individually with the same key, as in RC4 each byte is being encrypted with a stream generated by the key.

The only difference is that RC4 decryption is also just the RC4 encryption applied a second time.

    C(i) = K(i) ⊕ P(i)  ⇒  P(i) = C(i) ⊕ K(i)

In order to generate diffusion we just have to look at an operation mode for block ciphers that works as a stream cipher and propagates changes in the plaintext throughout the ciphertext. And indeed [Cipher Feedback][wiki_modes_CFB] (CFB) does exactly that. The plaintext is XOR'ed with a key stream that depends on the previous block of the ciphertext. Bringing it over to RC4 that means that the current byte of plaintext is XOR'ed with a key that depends on the previous byte of ciphertext. So instead of one bit flip at one position, the bit flip is propagated through the end of the ciphertext.

    C(0) = K(0) ⊕ IV ⊕ P(0)
    C(i) = K(i) ⊕ C(i-1) ⊕ P(i)   (i > 0)

`IV` denotes the [initialization vector][wiki_IV] which is just one hand picked constant byte that is used in lack of a ciphertext byte at position -1.

Chaining successive bytes that way breaks the symmetry between encryption and decryption of RC4. Before we could simply swap the ciphertext with the plaintext. Now we have a dependency to the previous byte of the ciphertext.

    C(i) = K(i) ⊕ C(i-1) ⊕ P(i)  ⇒  P(i) = C(i) ⊕ C(i-1) ⊕ K(i)

But this is not a big deal as one just has to carry the ciphertext from the previous iteration.

While the key stream is completely different, this modification is still not good enough. One bit flip in the plaintext is reflected as exactly the same bit flipped in every single successive byte of the ciphertext. To overcome this, we use the constantly changing S-Box of RC4 to mix it up even more.

    C(0) = K(0) ⊕ S[IV] ⊕ P(0)
    C(i) = K(i) ⊕ S[C(i-i)] ⊕ P(i)   (i > 0)

That way the ciphertext after that one bit flip changes in a way that cannot be overseen. But there is still a flaw. The ciphertext before the bit flip still did not change. To also improve this, we just reverse the ciphertext and encrypt it again using the same algorithm. This way a single bit flip is propagated forth and back and changes the entire ciphertext which is a level of diffusion that is higher than in block ciphers. So the high level encryption algorithm looks like this.

    key = "secret"
    plaintext = "Hello World!"
    intermediate = rc4_with_cfb_encrypt(plaintext, key)
    intermediate = reverse(intermediate)
    ciphertext   = re4_with_cfb_encrypt(intermediate, key)

While the decryption does the same in the reverse order using the same key but also using `rc4_with_cfb_decrypt` instead of `_encrypt`.

Compared to the original RC4 the code changes in the proposed RC4 encryption with CFB are pretty small.

    RC4 with CFB encryption:                                    RC4:

    s[256]                                                      s[256]
    s[i] := i ∀ i ∈ [0…255]                                     s[i] := i ∀ i ∈ [0…255]

    j := 0                                                      j := 0

    for i from 0 to 255:                                        for i from 0 to 255:
        j := (j + s[i] + key[i mod keyLength]) mod 256              j := (j + s[i] + key[i mod keyLength]) mod 256
        swap s[i] s[j]                                              swap s[i] s[j]
    end                                                         end

    i := 0                                                      i := 0
    j := 0                                                      j := 0

    for a from 0 to inputLength:                                for a from 0 to inputLength:
        i := (i + 1) mod 256                                        i := (i + 1) mod 256
        j := (j + s[i]) mod 256                                     j := (j + s[i]) mod 256
        swap s[i] s[j]                                              swap s[i] s[j]
        K := s[(s[i] + s[j]) mod 256];                              K := s[(s[i] + s[j]) mod 256];

        if a > 0:
            output[a] := K XOR s[output[a-1]] XOR input[a]          output[a] := K XOR input[a]
        else:
            output[a] := K XOR s[IV] XOR input[a]
        end
    end                                                         end

But because of the broken symmetry we need another function for the decryption. It is almost the same as for the encryption with the following small changes.

    RC4 with CFB encryption:                                    RC4 with CFB decryption:

    if a > 0:                                                   if a > 0:
        output[a] := K XOR s[output[a-1]] XOR input[a]              output[a] := K XOR s[input[a-1]] XOR input[a]
    else:                                                       else:
        output[a] := K XOR s[IV] XOR input[a]                       output[a] := K XOR s[IV] XOR input[a]
    end                                                         end

The Rivest Cipher 4 with Diffusion (RC4D) algorithm can still be optimized for use with embedded devices.

* A fixed key size with the length to the power of two (like in AES) replaces the `mod` operation with an `bitwise_and` during the S-Box initialization. (That also applies to all the other `mod` operations.)
* Using an in-place version saves memory.
* The whole code takes up as little as 492 bytes of flash memory.

### Comparison ###

Now we will compare the different ciphers in both execution time and used flash memory on an Arduino UNO R3. The lines annotated with "(opt)" show versions that have to some degree been optimized for the Arduino as opposed to naïve implementations. For comparable results the limitations of AES have been taken as the base. So the key is 128 bits long, while the plaintext with its length of 32 bytes spans two AES blocks. The source code can be found at [GitHub][github].

As part of optimizations, the RC4 and RC4D cipher have been imposed with some limitations from AES to make them both faster and smaller. This also makes the different cipher algorithms more comparable.

Implementations with a __k__ have a fixed key length of 16 bytes (128 bits). This lead to a more then 2x increase in speed and a decent size reduction.

Implementations with an __i__ perform the encryption in-place. This reduces the need for intermediate buffers. This reduces the pressure on the scarce RAM during en-/decryption and also provides a small increase in speed and a small reduction in size.

Implementations with a __p__ perform a precomputation of the S-Box using the key. Due to the aimed small plaintext size, the S-Box is very large compared to it and also the computation thereof. A precomputed S-Box reduces this overhead for every de-/encryption to just one call of `memcpy`. This provides a 3x speedup but comes at the expense of RAM. Moving this to EEPROM does not any good as one can see at the implementation with an __e__.

|      Type       | time _ms_ | space _bytes_ |               note                      |
|-----------------|----------:|--------------:|-----------------------------------------|
| AES             |     11040 |          1972 | occupies additional 562 bytes of RAM    |
| AES (opt)       |     11516 |          1936 |                                         |
| RC4             |      8856 |           394 |                                         |
| RC4 (opt)       |      4340 |           290 |                                         |
| RC4 k           |      1790 |           270 |                                         |
| RC4 k (opt)     |      1700 |           234 |                                         |
| RC4D            |     17619 |          1080 |                                         |
| RC4D (opt)      |      9054 |           674 |                                         |
| RC4D k          |      3719 |           612 |                                         |
| RC4D k (opt)    |      3719 |           612 |                                         |
| RC4D ki         |      3617 |           526 |                                         |
| RC4D ki (opt)   |      3482 |           492 |                                         |
| RC4D kip        |      1101 |           490 | occupies additional 256 bytes of RAM    |
| RC4D kip (opt)  |      1135 |           466 | occupies additional 256 bytes of RAM    |
| RC4D kipe       |      4309 |           724 | occupies additional 256 bytes of EEPROM |
| RC4D kipe (opt) |      4323 |           692 | occupies additional 256 bytes of EEPROM |

The row _time_ shows the measured time for 1024 iterations.

The following table summarizes the features of the different ciphers and implementations that have been compared

|        Feature     |  AES  |  RC4 | RC4 k | RC4D | RC4D k |
|--------------------|-------|------|-------|------|--------|
| Payload [bytes]    |   16  |  any |  any  |  any |   any  |
| Key length [bytes] |   16  |  any |   16  |  any |   16   |
| Diffusion          | block | none |  none | full |  full  |

### Remarks ###

All of the optimizations that have been applied to RC4D can also be applied to RC4. But I leave it as an exercise to the reader as I do not plan to use RC4 anyway. But none of those optimizations can be applied to AES because they are already there, like the fixed key length, or they cannot be applied due to the completely different algorithm.

## Conclusion ##

While derived from a stream cipher, the proposed algorithm RC4D is actually a block cipher with blocks of arbitrary length. Compared to AES, the algorithm is up to 10x faster, takes about only 1/4 of flash space and can be applied to plaintext of any length without padding. Compared to RC4 we traded the arbitrary key length and a 2x longer execution time and space consumption for a higher degree of security through diffusion. Yet RC4D still has potential for optimization in terms of security. For example the two stages during encryption and/or decryption may use different keys to further increase the security.

I am not an cryptographic expert so I can only describe my observations.

The original RC4 algorithm has not been modified. It is just being used in a different mode of operation. So in the worst case the algorithm is just as bad as the original RC4. But as the mode of operation strengthens block cipher one can assume that this is here the case as well.

Diffusion is a highly desirable property of a cipher. And here we have achieved a level of diffusion that affects the entire ciphertext. For large data this can even exceed the level of diffusion in block ciphers.

So in my humble opinion the presented method is much stronger than the original RC4. And due to its simplicity it is suited for use in embedded devices.

[github]: https://github.com/kwasmich/RC4D
[wiki_diffusion]: https://en.wikipedia.org/wiki/Confusion_and_diffusion
[wiki_AES]: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
[wiki_RC4]: https://en.wikipedia.org/wiki/RC4
[wiki_modes]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
[wiki_modes_ECB]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_(ECB)
[wiki_modes_CFB]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Feedback_(CFB)
[wiki_IV]: https://en.wikipedia.org/wiki/Initialization_vector

redpajama_set_name: RedPajamaGithub


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using zSprite;
using zSprite.Collections;

namespace GameName1.SRPG.Scripts
{
    public class TurnManager : Script
    {
        private static int turnId = 0;

        private interface IAction
        {
            int getExecuteTime();
            void Execute();
        }

        private struct Turn : IAction
        {
            public int id ;
            public int turn;
            public int speed;
            public GameObject gameObject;

            public int getExecuteTime()
            {
                return turn + speed;
            }

            public void Execute()
            {
                gameObject.sendMessage("executeTurn");
            }
        }

        private PriorityQueue<int, IAction> actionList = new PriorityQueue<int, IAction>();
        private int currentTurn = 0;

        public int CurrentTurn { get { return currentTurn; } }

        //private List<Turn> actions = new List<Turn>();
        //private List<Turn> characters = new List<Turn>();

        //private IEnumerable<Turn> allTurns()
        //{
        //    foreach (var a in actions)
        //        yield return a;

        //    foreach (var c in characters)
        //        yield return c;
        //}

        public int registerAction(GameObject go, int speed)
        {

            //var currentTime = Root.instance.time.time;
            //var actionTime = currentTime + speed;

            var nextid = turnId++;
            var turn = new Turn() { id = nextid, gameObject = go, speed = speed, turn = currentTurn };
            actionList.Enqueue(turn.getExecuteTime(), turn);

            return nextid;
        }

        public void cancelAction(int id)
        {

        }

        public void endTurn()
        {
            actionList.Dequeue();
        }

        private void update()
        {
            if (actionList.Count > 0)
            {
                var item = actionList.Peek();

                currentTurn = item.Key;
                item.Value.Execute();
            }
        }

        private void render()
        {

            //show next 5 turns in the top right
        }
    }
}


text:
namespace chromeos {

NfcManagerClient::Properties::Properties(
    dbus::ObjectProxy* object_proxy,
    const PropertyChangedCallback& callback)
    : NfcPropertySet(object_proxy,
                     nfc_manager::kNfcManagerInterface,
                     callback) {
  RegisterProperty(nfc_manager::kAdaptersProperty, &adapters);
}

NfcManagerClient::Properties::~Properties() {
}

// The NfcManagerClient implementation used in production.
class NfcManagerClientImpl : public NfcManagerClient {
 public:
  NfcManagerClientImpl()
      : object_proxy_(NULL),
        weak_ptr_factory_(this) {
  }

  ~NfcManagerClientImpl() override {}

  // NfcManagerClient override.
  void AddObserver(Observer* observer) override {
    DCHECK(observer);
    observers_.AddObserver(observer);
  }

  // NfcManagerClient override.
  void RemoveObserver(Observer* observer) override {
    DCHECK(observer);
    observers_.RemoveObserver(observer);
  }

  // NfcManagerClient override.
  Properties* GetProperties() override { return properties_.get(); }

 protected:
  // DBusClient override.
  void Init(dbus::Bus* bus) override {
    VLOG(1) << "Creating NfcManagerClientImpl";

    // Create the object proxy.
    object_proxy_ = bus->GetObjectProxy(
        nfc_manager::kNfcManagerServiceName,
        dbus::ObjectPath(nfc_manager::kNfcManagerServicePath));

    // Set up the signal handlers.
    object_proxy_->ConnectToSignal(
        nfc_manager::kNfcManagerInterface,
        nfc_manager::kAdapterAddedSignal,
        base::Bind(&NfcManagerClientImpl::AdapterAddedReceived,
                   weak_ptr_factory_.GetWeakPtr()),
        base::Bind(&NfcManagerClientImpl::AdapterAddedConnected,
                   weak_ptr_factory_.GetWeakPtr()));

    object_proxy_->ConnectToSignal(
        nfc_manager::kNfcManagerInterface,
        nfc_manager::kAdapterRemovedSignal,
        base::Bind(&NfcManagerClientImpl::AdapterRemovedReceived,
                   weak_ptr_factory_.GetWeakPtr()),
        base::Bind(&NfcManagerClientImpl::AdapterRemovedConnected,
                   weak_ptr_factory_.GetWeakPtr()));

    // Create the properties structure.
    properties_.reset(new Properties(
        object_proxy_,
        base::Bind(&NfcManagerClientImpl::OnPropertyChanged,
                   weak_ptr_factory_.GetWeakPtr())));

    properties_->ConnectSignals();
    properties_->GetAll();
  }

 private:
  // NFC manager signal handlers.
  void OnPropertyChanged(const std::string& property_name) {
    VLOG(1) << "NFC Manager property changed: " << property_name;
    FOR_EACH_OBSERVER(Observer, observers_,
                      ManagerPropertyChanged(property_name));
  }

  // Called by dbus:: when an "AdapterAdded" signal is received..
  void AdapterAddedReceived(dbus::Signal* signal) {
    DCHECK(signal);
    dbus::MessageReader reader(signal);
    dbus::ObjectPath object_path;
    if (!reader.PopObjectPath(&object_path)) {
      LOG(WARNING) << "AdapterAdded signal has incorrect parameters: "
                   << signal->ToString();
      return;
    }
    VLOG(1) << "Adapter added: " << object_path.value();
    FOR_EACH_OBSERVER(Observer, observers_, AdapterAdded(object_path));
  }

  // Called by dbus:: when the "AdapterAdded" signal is initially connected.
  void AdapterAddedConnected(const std::string& interface_name,
                             const std::string& signal_name,
                             bool success) {
    LOG_IF(WARNING, !success) << "Failed to connect to AdapterAdded signal.";
  }

  // Called by dbus:: when an "AdapterRemoved" signal is received..
  void AdapterRemovedReceived(dbus::Signal* signal) {
    DCHECK(signal);
    dbus::MessageReader reader(signal);
    dbus::ObjectPath object_path;
    if (!reader.PopObjectPath(&object_path)) {
      LOG(WARNING) << "AdapterRemoved signal has incorrect parameters: "
                   << signal->ToString();
      return;
    }
    VLOG(1) << "Adapter removed: " << object_path.value();
    FOR_EACH_OBSERVER(Observer, observers_, AdapterRemoved(object_path));
  }

  // Called by dbus:: when the "AdapterAdded" signal is initially connected.
  void AdapterRemovedConnected(const std::string& interface_name,
                               const std::string& signal_name,
                               bool success) {
    LOG_IF(WARNING, !success) << "Failed to connect to AdapterRemoved signal.";
  }

  // D-Bus proxy for neard Manager interface.
  dbus::ObjectProxy* object_proxy_;

  // Properties for neard Manager interface.
  scoped_ptr<Properties> properties_;

  // List of observers interested in event notifications.
  base::ObserverList<NfcManagerClient::Observer> observers_;

  // Weak pointer factory for generating 'this' pointers that might live longer
  // than we do.
  // Note: This should remain the last member so it'll be destroyed and
  // invalidate its weak pointers before any other members are destroyed.
  base::WeakPtrFactory<NfcManagerClientImpl> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(NfcManagerClientImpl);
};

NfcManagerClient::NfcManagerClient() {
}

NfcManagerClient::~NfcManagerClient() {
}

// static
NfcManagerClient* NfcManagerClient::Create() {
  return new NfcManagerClientImpl();
}

}  // namespace chromeos


text:
package it.polito.ai.polibox.client.swing.frames;

import it.polito.ai.polibox.client.notification.NotificationsInterface;
import it.polito.ai.polibox.client.persistency.Notification;
import it.polito.ai.polibox.client.xml.XmlLoaderInterface;

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GraphicsDevice;
import java.awt.GraphicsDevice.WindowTranslucency;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.util.Observable;
import java.util.Observer;
import java.util.ResourceBundle;

import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class TranslucentNotificationFrame extends JFrame implements ActionListener,InitializingBean,Observer {

	private static final long serialVersionUID = 7896341672746821233L;

	private Timer timer;

    private Point location;

    @Autowired
	private ResourceBundle resourceBundle;

	@Autowired
	private XmlLoaderInterface<NotificationsInterface> notificationManager;

    public XmlLoaderInterface<NotificationsInterface> getNotificationManager() {
		return notificationManager;
	}

	public void setNotificationManager(
			XmlLoaderInterface<NotificationsInterface> notificationManager) {
		this.notificationManager = notificationManager;
	}

	public ResourceBundle getResourceBundle() {
		return resourceBundle;
	}

	public void setResourceBundle(ResourceBundle resourceBundle) {
		this.resourceBundle = resourceBundle;
	}

	public Point getLocation() {
		return location;
	}

	public void setLocation(Point location) {
		super.setLocation(location);
		this.location = location;
	}

	public void afterPropertiesSet() throws Exception {
		setTitle(resourceBundle.getString("TranslucentNotificationFrame.afterPropertiesSet.title"));
		((Observable)notificationManager.load()).addObserver(this);
	}

	public TranslucentNotificationFrame() {
    	  super();
          setLayout(new FlowLayout());

          setSize(300,200);

          setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);

       // Determine if the GraphicsDevice supports translucency.
          GraphicsEnvironment ge =
              GraphicsEnvironment.getLocalGraphicsEnvironment();
          GraphicsDevice gd = ge.getDefaultScreenDevice();

          //If translucent windows aren't supported, exit.
          if (!gd.isWindowTranslucencySupported(WindowTranslucency.TRANSLUCENT)) {
              System.err.println("Translucency is not supported");
              System.exit(0);
          }

          setUndecorated(true);

          setOpacity(0.55f);
          // Display the window.
          setVisible(false);

    }

    public void actionPerformed(ActionEvent e) {
    	dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
    	getContentPane().removeAll();
    	setVisible(false);
    	timer.stop();
    	timer=null;
    }

	public void update(Observable o, Object arg) {
		getContentPane().add(buildNotification(((NotificationsInterface)o).getLast()));
		timer = new Timer(3000, this);
		timer.start();
		setVisible(true);
	}

	private JPanel buildNotification(Notification n){
		JPanel p=new JPanel(true);
		p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
		JLabel jtf=new JLabel(n.getCreationTime().toString());
		jtf.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 16));
		jtf.setForeground(new Color(88,88,88));
		jtf.enableInputMethods(false);
		JLabel jta=new JLabel(n.getDescription());
		jta.setForeground(new Color(11,11,11));
		jta.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 16));
		jta.enableInputMethods(false);
		p.add(jtf);
		p.add(jta);
		p.setVisible(true);
		return p;
	}
}


text:
/** PURE_IMPORTS_START .._.._Observable,.._.._observable_range PURE_IMPORTS_END */
import { Observable } from '../../Observable';
import { range as staticRange } from '../../observable/range';
Observable.range = staticRange;
//# sourceMappingURL=range.js.map


text:
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

## [v0.11.2] - 2021-03-25

## Fixed

- Added missing allocator type parameter to `HashMap`'s and `HashSet`'s `Clone` impls. (#252)

## [v0.11.1] - 2021-03-20

## Fixed

- Added missing `pub` modifier to `BumpWrapper`. (#251)

## [v0.11.0] - 2021-03-14

## Added
- Added safe `try_insert_no_grow` method to `RawTable`. (#229)
- Added support for `bumpalo` as an allocator without the `nightly` feature. (#231)
- Implemented `Default` for `RawTable`. (#237)
- Added new safe methods `RawTable::get_each_mut`, `HashMap::get_each_mut`, and
  `HashMap::get_each_key_value_mut`. (#239)
- Added `From<HashMap<T, ()>>` for `HashSet<T>`. (#235)
- Added `try_insert` method to `HashMap`. (#247)

## Changed
- The minimum Rust version has been bumped to 1.49.0. (#230)
- Significantly improved compilation times by reducing the amount of generated IR. (#205)

## Removed
- We no longer re-export the unstable allocator items from the standard library, nor the stable shims approximating the same. (#227)
- Removed hasher specialization support from `aHash`, which was resulting in inconsistent hashes being generated for a key. (#248)

## Fixed
- Fixed union length comparison. (#228)

## ~~[v0.10.0] - 2021-01-16~~

This release was _yanked_ due to inconsistent hashes being generated with the `nightly` feature. (#248)

## Changed
- Parametrized `RawTable`, `HashSet` and `HashMap` over an allocator. (#133)
- Improved branch prediction hints on stable. (#209)
- Optimized hashing of primitive types with AHash using specialization. (#207)
- Only instantiate `RawTable`'s reserve functions once per key-value. (#204)

## [v0.9.1] - 2020-09-28

## Added
- Added safe methods to `RawTable` (#202):
  - `get`: `find` and `as_ref`
  - `get_mut`: `find` and `as_mut`
  - `insert_entry`: `insert` and `as_mut`
  - `remove_entry`: `find` and `remove`
  - `erase_entry`: `find` and `erase`

## Changed
- Removed `from_key_hashed_nocheck`'s `Q: Hash`. (#200)
- Made `RawTable::drain` safe. (#201)

## [v0.9.0] - 2020-09-03

### Fixed
- `drain_filter` now removes and yields items that do match the predicate,
  rather than items that don't.  This is a **breaking change** to match the
  behavior of the `drain_filter` methods in `std`. (#187)

### Added
- Added `replace_entry_with` to `OccupiedEntry`, and `and_replace_entry_with` to `Entry`. (#190)
- Implemented `FusedIterator` and `size_hint` for `DrainFilter`. (#188)

### Changed
- The minimum Rust version has been bumped to 1.36 (due to `crossbeam` dependency). (#193)
- Updated `ahash` dependency to 0.4. (#198)
- `HashMap::with_hasher` and `HashSet::with_hasher` are now `const fn`. (#195)
- Removed `T: Hash + Eq` and `S: BuildHasher` bounds on `HashSet::new`,
  `with_capacity`, `with_hasher`, and `with_capacity_and_hasher`.  (#185)

## [v0.8.2] - 2020-08-08

### Changed
- Avoid closures to improve compile times. (#183)
- Do not iterate to drop if empty. (#182)

## [v0.8.1] - 2020-07-16

### Added
- Added `erase` and `remove` to `RawTable`. (#171)
- Added `try_with_capacity` to `RawTable`. (#174)
- Added methods that allow re-using a `RawIter` for `RawDrain`,
  `RawIntoIter`, and `RawParIter`. (#175)
- Added `reflect_remove` and `reflect_insert` to `RawIter`. (#175)
- Added a `drain_filter` function to `HashSet`. (#179)

### Changed
- Deprecated `RawTable::erase_no_drop` in favor of `erase` and `remove`. (#176)
- `insert_no_grow` is now exposed under the `"raw"` feature. (#180)

## [v0.8.0] - 2020-06-18

### Fixed
- Marked `RawTable::par_iter` as `unsafe`. (#157)

### Changed
- Reduced the size of `HashMap`. (#159)
- No longer create tables with a capacity of 1 element. (#162)
- Removed `K: Eq + Hash` bounds on `retain`. (#163)
- Pulled in `HashMap` changes from rust-lang/rust (#164):
  - `extend_one` support on nightly.
  - `CollectionAllocErr` renamed to `TryReserveError`.
  - Added `HashSet::get_or_insert_owned`.
  - `Default` for `HashSet` no longer requires `T: Eq + Hash` and `S: BuildHasher`.

## [v0.7.2] - 2020-04-27

### Added
- Added `or_insert_with_key` to `Entry`. (#152)

### Fixed
- Partially reverted `Clone` optimization which was unsound. (#154)

### Changed
- Disabled use of `const-random` by default, which prevented reproducible builds. (#155)
- Optimized `repeat` function. (#150)
- Use `NonNull` for buckets, which improves codegen for iterators. (#148)

## [v0.7.1] - 2020-03-16

### Added
- Added `HashMap::get_key_value_mut`. (#145)

### Changed
- Optimized `Clone` implementation. (#146)

## [v0.7.0] - 2020-01-31

### Added
- Added a `drain_filter` function to `HashMap`. (#135)

### Changed
- Updated `ahash` dependency to 0.3. (#141)
- Optimized set union and intersection. (#130)
- `raw_entry` can now be used without requiring `S: BuildHasher`. (#123)
- `RawTable::bucket_index` can now be used under the `raw` feature. (#128)

## [v0.6.3] - 2019-10-31

### Added
- Added an `ahash-compile-time-rng` feature (enabled by default) which allows disabling the
  `compile-time-rng` feature in `ahash` to work around a Cargo bug. (#125)

## [v0.6.2] - 2019-10-23

### Added
- Added an `inline-more` feature (enabled by default) which allows choosing a tradeoff between
  runtime performance and compilation time. (#119)

## [v0.6.1] - 2019-10-04

### Added
- Added `Entry::insert` and `RawEntryMut::insert`. (#118)

### Changed
- `Group::static_empty` was changed from a `const` to a `static` (#116).

## [v0.6.0] - 2019-08-13

### Fixed
- Fixed AHash accidentally depending on `std`. (#110)

### Changed
- The minimum Rust version has been bumped to 1.32 (due to `rand` dependency).

## ~~[v0.5.1] - 2019-08-04~~

This release was _yanked_ due to a breaking change for users of `no-default-features`.

### Added
- The experimental and unsafe `RawTable` API is available under the "raw" feature. (#108)
- Added entry-like methods for `HashSet`. (#98)

### Changed
- Changed the default hasher from FxHash to AHash. (#97)
- `hashbrown` is now fully `no_std` on recent Rust versions (1.36+). (#96)

### Fixed
- We now avoid growing the table during insertions when it wasn't necessary. (#106)
- `RawOccupiedEntryMut` now properly implements `Send` and `Sync`. (#100)
- Relaxed `lazy_static` version. (#92)

## [v0.5.0] - 2019-06-12

### Fixed
- Resize with a more conservative amount of space after deletions. (#86)

### Changed
- Exposed the Layout of the failed allocation in CollectionAllocErr::AllocErr. (#89)

## [v0.4.0] - 2019-05-30

### Fixed
- Fixed `Send` trait bounds on `IterMut` not matching the libstd one. (#82)

## [v0.3.1] - 2019-05-30

### Fixed
- Fixed incorrect use of slice in unsafe code. (#80)

## [v0.3.0] - 2019-04-23

### Changed
- Changed shrink_to to not panic if min_capacity < capacity. (#67)

### Fixed
- Worked around emscripten bug emscripten-core/emscripten-fastcomp#258. (#66)

## [v0.2.2] - 2019-04-16

### Fixed
- Inlined non-nightly lowest_set_bit_nonzero. (#64)
- Fixed build on latest nightly. (#65)

## [v0.2.1] - 2019-04-14

### Changed
- Use for_each in map Extend and FromIterator. (#58)
- Improved worst-case performance of HashSet.is_subset. (#61)

### Fixed
- Removed incorrect debug_assert. (#60)

## [v0.2.0] - 2019-03-31

### Changed
- The code has been updated to Rust 2018 edition. This means that the minimum
  Rust version has been bumped to 1.31 (2018 edition).

### Added
- Added `insert_with_hasher` to the raw_entry API to allow `K: !(Hash + Eq)`. (#54)
- Added support for using hashbrown as the hash table implementation in libstd. (#46)

### Fixed
- Fixed cargo build with minimal-versions. (#45)
- Fixed `#[may_dangle]` attributes to match the libstd `HashMap`. (#46)
- ZST keys and values are now handled properly. (#46)

## [v0.1.8] - 2019-01-14

### Added
- Rayon parallel iterator support (#37)
- `raw_entry` support (#31)
- `#[may_dangle]` on nightly (#31)
- `try_reserve` support (#31)

### Fixed
- Fixed variance on `IterMut`. (#31)

## [v0.1.7] - 2018-12-05

### Fixed
- Fixed non-SSE version of convert_special_to_empty_and_full_to_deleted. (#32)
- Fixed overflow in rehash_in_place. (#33)

## [v0.1.6] - 2018-11-17

### Fixed
- Fixed compile error on nightly. (#29)

## [v0.1.5] - 2018-11-08

### Fixed
- Fixed subtraction overflow in generic::Group::match_byte. (#28)

## [v0.1.4] - 2018-11-04

### Fixed
- Fixed a bug in the `erase_no_drop` implementation. (#26)

## [v0.1.3] - 2018-11-01

### Added
- Serde support. (#14)

### Fixed
- Make the compiler inline functions more aggressively. (#20)

## [v0.1.2] - 2018-10-31

### Fixed
- `clear` segfaults when called on an empty table. (#13)

## [v0.1.1] - 2018-10-30

### Fixed
- `erase_no_drop` optimization not triggering in the SSE2 implementation. (#3)
- Missing `Send` and `Sync` for hash map and iterator types. (#7)
- Bug when inserting into a table smaller than the group width. (#5)

## v0.1.0 - 2018-10-29

- Initial release

[Unreleased]: https://github.com/rust-lang/hashbrown/compare/v0.11.2...HEAD
[v0.11.2]: https://github.com/rust-lang/hashbrown/compare/v0.11.1...v0.11.2
[v0.11.1]: https://github.com/rust-lang/hashbrown/compare/v0.11.0...v0.11.1
[v0.11.0]: https://github.com/rust-lang/hashbrown/compare/v0.10.0...v0.11.0
[v0.10.0]: https://github.com/rust-lang/hashbrown/compare/v0.9.1...v0.10.0
[v0.9.1]: https://github.com/rust-lang/hashbrown/compare/v0.9.0...v0.9.1
[v0.9.0]: https://github.com/rust-lang/hashbrown/compare/v0.8.2...v0.9.0
[v0.8.2]: https://github.com/rust-lang/hashbrown/compare/v0.8.1...v0.8.2
[v0.8.1]: https://github.com/rust-lang/hashbrown/compare/v0.8.0...v0.8.1
[v0.8.0]: https://github.com/rust-lang/hashbrown/compare/v0.7.2...v0.8.0
[v0.7.2]: https://github.com/rust-lang/hashbrown/compare/v0.7.1...v0.7.2
[v0.7.1]: https://github.com/rust-lang/hashbrown/compare/v0.7.0...v0.7.1
[v0.7.0]: https://github.com/rust-lang/hashbrown/compare/v0.6.3...v0.7.0
[v0.6.3]: https://github.com/rust-lang/hashbrown/compare/v0.6.2...v0.6.3
[v0.6.2]: https://github.com/rust-lang/hashbrown/compare/v0.6.1...v0.6.2
[v0.6.1]: https://github.com/rust-lang/hashbrown/compare/v0.6.0...v0.6.1
[v0.6.0]: https://github.com/rust-lang/hashbrown/compare/v0.5.1...v0.6.0
[v0.5.1]: https://github.com/rust-lang/hashbrown/compare/v0.5.0...v0.5.1
[v0.5.0]: https://github.com/rust-lang/hashbrown/compare/v0.4.0...v0.5.0
[v0.4.0]: https://github.com/rust-lang/hashbrown/compare/v0.3.1...v0.4.0
[v0.3.1]: https://github.com/rust-lang/hashbrown/compare/v0.3.0...v0.3.1
[v0.3.0]: https://github.com/rust-lang/hashbrown/compare/v0.2.2...v0.3.0
[v0.2.2]: https://github.com/rust-lang/hashbrown/compare/v0.2.1...v0.2.2
[v0.2.1]: https://github.com/rust-lang/hashbrown/compare/v0.2.0...v0.2.1
[v0.2.0]: https://github.com/rust-lang/hashbrown/compare/v0.1.8...v0.2.0
[v0.1.8]: https://github.com/rust-lang/hashbrown/compare/v0.1.7...v0.1.8
[v0.1.7]: https://github.com/rust-lang/hashbrown/compare/v0.1.6...v0.1.7
[v0.1.6]: https://github.com/rust-lang/hashbrown/compare/v0.1.5...v0.1.6
[v0.1.5]: https://github.com/rust-lang/hashbrown/compare/v0.1.4...v0.1.5
[v0.1.4]: https://github.com/rust-lang/hashbrown/compare/v0.1.3...v0.1.4
[v0.1.3]: https://github.com/rust-lang/hashbrown/compare/v0.1.2...v0.1.3
[v0.1.2]: https://github.com/rust-lang/hashbrown/compare/v0.1.1...v0.1.2
[v0.1.1]: https://github.com/rust-lang/hashbrown/compare/v0.1.0...v0.1.1


text:
/*
 * ITCompression.cpp
 * -----------------
 * Purpose: Code for IT sample compression and decompression.
 * Notes  : The original Python compression code was written by GreaseMonkey and has been released into the public domain.
 * Authors: OpenMPT Devs
 *          Ben "GreaseMonkey" Russell
 * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
 */

#include <stdafx.h>
#include "ITCompression.h"
#include "../common/misc_util.h"

// Algorithm parameters for 16-Bit samples
struct IT16BitParams
{
	typedef int16 sample_t;
	static const int16 lowerTab[];
	static const int16 upperTab[];
	static const int fetchA = 4, lowerB = -8, upperB = 7, defWidth = 17;
	static int Clamp(sample_t v) { return int(v) & 0xFFFF; }
};

const int16 IT16BitParams::lowerTab[] = { 0, -1, -3, -7, -15, -31, -56, -120, -248, -504, -1016, -2040, -4088, -8184, -16376, -32760, -32768 };
const int16 IT16BitParams::upperTab[] = { 0, 1, 3, 7, 15, 31, 55, 119, 247, 503, 1015, 2039, 4087, 8183, 16375, 32759, 32767 };

// Algorithm parameters for 8-Bit samples
struct IT8BitParams
{
	typedef int8 sample_t;
	static const int8 lowerTab[];
	static const int8 upperTab[];
	static const int fetchA = 3, lowerB = -4, upperB = 3, defWidth = 9;
	static int Clamp(sample_t v) { return int(v) & 0xFF; }
};

const int8 IT8BitParams::lowerTab[] = { 0, -1, -3, -7, -15, -31, -60, -124, -128 };
const int8 IT8BitParams::upperTab[] = { 0, 1, 3, 7, 15, 31, 59, 123, 127 };

static const int ITWidthChangeSize[] = { 4, 5, 6, 7, 8, 9, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 };

//////////////////////////////////////////////////////////////////////////////
// IT 2.14 compression

ITCompression::ITCompression(const ModSample &sample, bool it215, FILE *f) : file(f), mptSample(sample), is215(it215)
//-------------------------------------------------------------------------------------------------------------------
{
	packedData = new (std::nothrow) uint8[bufferSize];
	sampleData = new (std::nothrow) uint8[blockSize];
	packedTotalLength = 0;
	if(packedData == nullptr || sampleData == nullptr)
	{
		return;
	}

	for(uint8 chn = 0; chn < mptSample.GetNumChannels(); chn++)
	{
		SmpLength offset = 0;
		SmpLength remain = mptSample.nLength;
		while(remain > 0)
		{
			// Initialise output buffer and bit writer positions
			packedLength = 2;
			bitPos = 0;
			remBits = 8;
			byteVal = 0;

			if(mptSample.GetElementarySampleSize() > 1)
				Compress<IT16BitParams>(static_cast<const int16 *>(sample.pSample) + chn, offset, remain);
			else
				Compress<IT8BitParams>(static_cast<const int8 *>(sample.pSample) + chn, offset, remain);

			if(file) fwrite(&packedData[0], packedLength, 1, file);
			packedTotalLength += packedLength;

			offset += baseLength;
			remain -= baseLength;
		}
	}

	delete[] packedData;
	delete[] reinterpret_cast<uint8*>(sampleData);
}

template<typename T>
void ITCompression::CopySample(void *target, const void *source, SmpLength offset, SmpLength length, SmpLength skip)
//------------------------------------------------------------------------------------------------------------------
{
	T *out = static_cast<T *>(target);
	const T *in = static_cast<const T *>(source) + offset * skip;
	for(SmpLength i = 0, j = 0; j < length; i += skip, j++)
	{
		out[j] = in[i];
	}
}

// Convert sample to delta values.
template<typename T>
void ITCompression::Deltafy()
//---------------------------
{
	T *p = static_cast<T *>(sampleData);
	int oldVal = 0;
	for(SmpLength i = 0; i < baseLength; i++)
	{
		int newVal = p[i];
		p[i] = static_cast<T>(newVal - oldVal);
		oldVal = newVal;
	}
}

template<typename Properties>
void ITCompression::Compress(const void *data, SmpLength offset, SmpLength actualLength)
//--------------------------------------------------------------------------------------
{
	baseLength = std::min(actualLength, SmpLength(blockSize / sizeof(typename Properties::sample_t)));

	CopySample<typename Properties::sample_t>(sampleData, data, offset, baseLength, mptSample.GetNumChannels());

	Deltafy<typename Properties::sample_t>();
	if(is215)
	{
		Deltafy<typename Properties::sample_t>();
	}

	const int defWidth = Properties::defWidth; // gcc static const member reference workaround

	// Initialise bit width table with initial values
	bwt.assign(baseLength, defWidth);

	// Recurse!
	SquishRecurse<Properties>(defWidth, defWidth, defWidth, defWidth - 2, 0, baseLength);

	// Write those bits!
	const typename Properties::sample_t *p = static_cast<typename Properties::sample_t *>(sampleData);
	int width = defWidth;
	for(size_t i = 0; i < baseLength; i++)
	{
		if(bwt[i] != width)
		{
			if(width <= 6)
			{
				// Mode A: 1 to 6 bits
				ASSERT(width);
				WriteBits(width, (1 << (width - 1)));
				WriteBits(Properties::fetchA, ConvertWidth(width, bwt[i]));
			} else if(width < defWidth)
			{
				// Mode B: 7 to 8 / 16 bits
				int xv = (1 << (width - 1)) + Properties::lowerB + ConvertWidth(width, bwt[i]);
				WriteBits(width, xv);
			} else
			{
				// Mode C: 9 / 17 bits
				ASSERT((bwt[i] - 1) >= 0);
				WriteBits(width, (1 << (width - 1)) + bwt[i] - 1);
			}

			width = bwt[i];
		}
		WriteBits(width, Properties::Clamp(p[i]));
	}

	// Write last byte and update block length
	WriteByte(byteVal);
	packedData[0] = uint8((packedLength - 2) & 0xFF);
	packedData[1] = uint8((packedLength - 2) >> 8);
}

int ITCompression::GetWidthChangeSize(int w, bool is16)
//-----------------------------------------------------
{
	ASSERT(w > 0 && static_cast<unsigned int>(w) <= CountOf(ITWidthChangeSize));
	int wcs = ITWidthChangeSize[w - 1];
	if(w <= 6 && is16)
		wcs++;
	return wcs;
}

template<typename Properties>
void ITCompression::SquishRecurse(int sWidth, int lWidth, int rWidth, int width, SmpLength offset, SmpLength length)
//------------------------------------------------------------------------------------------------------------------
{
	if(width + 1 < 1)
	{
		for(SmpLength i = offset; i < offset + length; i++)
			bwt[i] = sWidth;
		return;
	}

	ASSERT(width >= 0 && static_cast<unsigned int>(width) < CountOf(Properties::lowerTab));

	SmpLength i = offset;
	SmpLength end = offset + length;
	const typename Properties::sample_t *p = static_cast<typename Properties::sample_t *>(sampleData);

	while(i < end)
	{
		if(p[i] >= Properties::lowerTab[width] && p[i] <= Properties::upperTab[width])
		{
			SmpLength start = i;
			// Check for how long we can keep this bit width
			while(i < end && p[i] >= Properties::lowerTab[width] && p[i] <= Properties::upperTab[width])
			{
				i++;
			}

			const SmpLength blockLength = i - start;
			const int xlwidth = start == offset ? lWidth : sWidth;
			const int xrwidth = i == end ? rWidth : sWidth;

			const bool is16 = sizeof(typename Properties::sample_t) > 1;
			const int wcsl = GetWidthChangeSize(xlwidth, is16);
			const int wcss = GetWidthChangeSize(sWidth, is16);
			const int wcsw = GetWidthChangeSize(width + 1, is16);

			bool comparison;
			if(i == baseLength)
			{
				SmpLength keepDown = wcsl + (width + 1) * blockLength;
				SmpLength levelLeft = wcsl + sWidth * blockLength;

				if(xlwidth == sWidth)
					levelLeft -= wcsl;

				comparison = (keepDown <= levelLeft);
			} else
			{
				SmpLength keepDown = wcsl + (width + 1) * blockLength + wcsw;
				SmpLength levelLeft = wcsl + sWidth * blockLength + wcss;

				if(xlwidth == sWidth)
					levelLeft -= wcsl;
				if(xrwidth == sWidth)
					levelLeft -= wcss;

				comparison = (keepDown <= levelLeft);
			}
			SquishRecurse<Properties>(comparison ? (width + 1) : sWidth, xlwidth, xrwidth, width - 1, start, blockLength);
		} else
		{
			bwt[i] = sWidth;
			i++;
		}
	}
}

int ITCompression::ConvertWidth(int curWidth, int newWidth)
//---------------------------------------------------------
{
	curWidth--;
	newWidth--;
	ASSERT(newWidth != curWidth);
	if(newWidth > curWidth)
		newWidth--;
	return newWidth;
}

void ITCompression::WriteBits(int width, int v)
//---------------------------------------------
{
	while(width > remBits)
	{
		byteVal |= (v << bitPos);
		width -= remBits;
		v >>= remBits;
		bitPos = 0;
		remBits = 8;
		WriteByte(byteVal);
		byteVal = 0;
	}

	if(width > 0)
	{
		byteVal |= (v & ((1 << width) - 1)) << bitPos;
		remBits -= width;
		bitPos += width;
	}
}

void ITCompression::WriteByte(uint8 v)
//------------------------------------
{
	if(packedLength < bufferSize)
	{
		packedData[packedLength++] = v;
	} else
	{
		// How could this happen, anyway?
		ASSERT(false);
	}
}

//////////////////////////////////////////////////////////////////////////////
// IT 2.14 decompression

ITDecompression::ITDecompression(FileReader &file, ModSample &sample, bool it215) : mptSample(sample), is215(it215)
//-----------------------------------------------------------------------------------------------------------------
{
	for(uint8 chn = 0; chn < mptSample.GetNumChannels(); chn++)
	{
		writtenSamples = writePos = 0;
		while(writtenSamples < sample.nLength && file.AreBytesLeft())
		{
			chunk = file.GetChunk(file.ReadUint16LE());

			// Initialise bit reader
			dataPos = 0;
			bitPos = 0;
			remBits = 8;
			mem1 = mem2 = 0;

			if(mptSample.GetElementarySampleSize() > 1)
				Uncompress<IT16BitParams>(static_cast<int16 *>(mptSample.pSample) + chn);
			else
				Uncompress<IT8BitParams>(static_cast<int8 *>(mptSample.pSample) + chn);
		}
	}
}

template<typename Properties>
void ITDecompression::Uncompress(void *target)
//--------------------------------------------
{
	curLength = std::min(mptSample.nLength - writtenSamples, SmpLength(ITCompression::blockSize / sizeof(typename Properties::sample_t)));

	const int defWidth = Properties::defWidth; // gcc static const member reference workaround

	int width = defWidth;
	while(curLength > 0)
	{
		if(width < 1 || width > defWidth || dataPos >= chunk.GetLength())
		{
			// Error!
			return;
		}

		int v = ReadBits(width);
		const int topBit = (1 << (width - 1));
		if(width <= 6)
		{
			// Mode A: 1 to 6 bits
			if(v == topBit)
				ChangeWidth(width, ReadBits(Properties::fetchA));
			else
				Write<Properties>(v, topBit, target);
		} else if(width < defWidth)
		{
			// Mode B: 7 to 8 / 16 bits
			if(v >= topBit + Properties::lowerB && v <= topBit + Properties::upperB)
				ChangeWidth(width, v - (topBit + Properties::lowerB));
			else
				Write<Properties>(v, topBit, target);
		} else
		{
			// Mode C: 9 / 17 bits
			if(v & topBit)
				width = (v & ~topBit) + 1;
			else
				Write<Properties>((v & ~topBit), 0, target);
		}
	}
}

void ITDecompression::ChangeWidth(int &curWidth, int width)
//---------------------------------------------------------
{
	width++;
	if(width >= curWidth)
		width++;

	ASSERT(curWidth != width);
	curWidth = width;
}

int ITDecompression::ReadBits(int width)
//--------------------------------------
{
	const uint8 *data = reinterpret_cast<const uint8 *>(chunk.GetRawData());
	int v = 0, vPos = 0, vMask = (1 << width) - 1;
	while(width >= remBits && dataPos < chunk.GetLength())
	{
		v |= (data[dataPos] >> bitPos) << vPos;
		vPos += remBits;
		width -= remBits;
		dataPos++;
		remBits = 8;
		bitPos = 0;
	}

	if(width > 0 && dataPos < chunk.GetLength())
	{
		v |= (data[dataPos] >> bitPos) << vPos;
		v &= vMask;
		remBits -= width;
		bitPos += width;
	}
	return v;
}

template<typename Properties>
void ITDecompression::Write(int v, int topBit, void *target)
//----------------------------------------------------------
{
	if(v & topBit)
		v -= (topBit << 1);
	mem1 += v;
	mem2 += mem1;
	static_cast<typename Properties::sample_t *>(target)[writePos] = static_cast<typename Properties::sample_t>(is215 ? (int)mem2 : (int)mem1);
	writtenSamples++;
	writePos += mptSample.GetNumChannels();
	curLength--;
}


text:
package com.linecorp.bot.servlet;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.mock.web.MockHttpServletRequest;

import com.google.common.io.ByteStreams;

import com.linecorp.bot.client.LineSignatureValidator;
import com.linecorp.bot.model.event.CallbackRequest;
import com.linecorp.bot.model.event.Event;
import com.linecorp.bot.model.event.MessageEvent;
import com.linecorp.bot.model.event.message.TextMessageContent;

@RunWith(MockitoJUnitRunner.class)
public class LineBotCallbackRequestParserTest {
    @Mock
    private HttpServletResponse response;

    @Spy
    private LineSignatureValidator lineSignatureValidator = new LineSignatureValidator(
            "SECRET".getBytes(StandardCharsets.UTF_8));

    private LineBotCallbackRequestParser lineBotCallbackRequestParser;

    public LineBotCallbackRequestParserTest() throws InvalidKeyException, NoSuchAlgorithmException {
    }

    @Before
    public void before() throws IOException {
        when(response.getWriter())
                .thenReturn(mock(PrintWriter.class));
        this.lineBotCallbackRequestParser = new LineBotCallbackRequestParser(lineSignatureValidator);
    }

    @Test
    public void testMissingHeader() throws Exception {
        MockHttpServletRequest request = new MockHttpServletRequest();

        assertThatThrownBy(() -> lineBotCallbackRequestParser.handle(request))
                .isInstanceOf(LineBotCallbackException.class)
                .hasMessage("Missing 'X-Line-Signature' header");
    }

    @Test
    public void testMissingHeader2() throws Exception {
        assertThatThrownBy(() -> lineBotCallbackRequestParser.handle("", ""))
        .isInstanceOf(LineBotCallbackException.class)
        .hasMessage("Missing 'X-Line-Signature' header");
    }

    @Test
    public void testInvalidSignature() throws Exception {
        MockHttpServletRequest request = new MockHttpServletRequest();
        request.addHeader("X-Line-Signature", "SSSSIGNATURE");
        request.setContent("{}".getBytes(StandardCharsets.UTF_8));

        assertThatThrownBy(() -> lineBotCallbackRequestParser.handle(request))
                .isInstanceOf(LineBotCallbackException.class)
                .hasMessage("Invalid API signature");
    }

    @Test
    public void testInvalidSignature2() throws Exception {
        final String signature="SSSSIGNATURE";
        final String content="{}";

        assertThatThrownBy(() -> lineBotCallbackRequestParser.handle(signature, content))
        .isInstanceOf(LineBotCallbackException.class)
        .hasMessage("Invalid API signature");
    }

    @Test
    public void testNullRequest() throws Exception {
        final byte[] requestBody = "null".getBytes(StandardCharsets.UTF_8);

        MockHttpServletRequest request = new MockHttpServletRequest();
        request.addHeader("X-Line-Signature", "SSSSIGNATURE");
        request.setContent(requestBody);

        doReturn(true).when(lineSignatureValidator).validateSignature(requestBody, "SSSSIGNATURE");

        assertThatThrownBy(() -> lineBotCallbackRequestParser.handle(request))
                .isInstanceOf(LineBotCallbackException.class)
                .hasMessage("Invalid content");
    }

    @Test
    public void testNullRequest2() throws Exception {
        final String signature="SSSSIGNATURE";
        final String content="null";

        doReturn(true).when(lineSignatureValidator).validateSignature(content.getBytes(StandardCharsets.UTF_8), signature);

        assertThatThrownBy(() -> lineBotCallbackRequestParser.handle(signature, content))
        .isInstanceOf(LineBotCallbackException.class)
        .hasMessage("Invalid content");
    }

    @Test
    public void testCallRequest() throws Exception {
        InputStream resource = getClass().getClassLoader().getResourceAsStream("callback-request.json");
        byte[] requestBody = ByteStreams.toByteArray(resource);

        MockHttpServletRequest request = new MockHttpServletRequest();
        request.addHeader("X-Line-Signature", "SSSSIGNATURE");
        request.setContent(requestBody);

        doReturn(true).when(lineSignatureValidator).validateSignature(requestBody, "SSSSIGNATURE");

        CallbackRequest callbackRequest = lineBotCallbackRequestParser.handle(request);

        assertThat(callbackRequest).isNotNull();

        final List<Event> result = callbackRequest.getEvents();

        final MessageEvent messageEvent = (MessageEvent) result.get(0);
        final TextMessageContent text = (TextMessageContent) messageEvent.getMessage();
        assertThat(text.getText()).isEqualTo("Hello, world");

        final String followedUserId = messageEvent.getSource().getUserId();
        assertThat(followedUserId).isEqualTo("u206d25c2ea6bd87c17655609a1c37cb8");
        assertThat(messageEvent.getTimestamp()).isEqualTo(Instant.parse("2016-05-07T13:57:59.859Z"));
    }

    @Test
    public void testCallRequest2() throws Exception {
        InputStream resource = getClass().getClassLoader().getResourceAsStream("callback-request.json");
        byte[] requestBody = ByteStreams.toByteArray(resource);

        MockHttpServletRequest request = new MockHttpServletRequest();
        request.addHeader("X-Line-Signature", "SSSSIGNATURE");
        request.setContent(requestBody);

        doReturn(true).when(lineSignatureValidator).validateSignature(requestBody, "SSSSIGNATURE");

        CallbackRequest callbackRequest = lineBotCallbackRequestParser.handle("SSSSIGNATURE", new String(requestBody, StandardCharsets.UTF_8));

        assertThat(callbackRequest).isNotNull();

        final List<Event> result = callbackRequest.getEvents();

        final MessageEvent messageEvent = (MessageEvent) result.get(0);
        final TextMessageContent text = (TextMessageContent) messageEvent.getMessage();
        assertThat(text.getText()).isEqualTo("Hello, world");

        final String followedUserId = messageEvent.getSource().getUserId();
        assertThat(followedUserId).isEqualTo("u206d25c2ea6bd87c17655609a1c37cb8");
        assertThat(messageEvent.getTimestamp()).isEqualTo(Instant.parse("2016-05-07T13:57:59.859Z"));
    }
}


text: Static files and example for my blog thatjavathing.blogspot.com


text:
// flow-typed signature: c0c09b83d9159e7a6e2bbc7eb089e42f
// flow-typed version: <<STUB>>/stream-to-blob-url_v^2.1.1/flow_v0.94.0

/**
 * This is an autogenerated libdef stub for:
 *
 *   'stream-to-blob-url'
 *
 * Fill this stub out by replacing all the `any` types.
 *
 * Once filled out, we encourage you to share your work with the
 * community by sending a pull request to:
 * https://github.com/flowtype/flow-typed
 */

declare module 'stream-to-blob-url' {
  declare module.exports: any;
}

/**
 * We include stubs for each file inside this npm package in case you need to
 * require those files directly. Feel free to delete any files that aren't
 * needed.
 */

// Filename aliases
declare module 'stream-to-blob-url/index' {
  declare module.exports: $Exports<'stream-to-blob-url'>;
}
declare module 'stream-to-blob-url/index.js' {
  declare module.exports: $Exports<'stream-to-blob-url'>;
}


text:
package org.xmlcml.ami2.plugins.gene;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.xmlcml.ami2.plugins.AMIPlugin;

/** test plugin.
 *
 * Very simple tasks for testing and tutorials.
 *
 * @author pm286
 *
 */
public class GenePlugin extends AMIPlugin {

	private static final Logger LOG = Logger.getLogger(GenePlugin.class);
	static {
		LOG.setLevel(Level.DEBUG);
	}

	public GenePlugin() {
		this.argProcessor = new GeneArgProcessor();
	}

	public GenePlugin(String[] args) {
		super();
		this.argProcessor = new GeneArgProcessor(args);
	}

	public GenePlugin(String args) {
		super();
		this.argProcessor = new GeneArgProcessor(args);
	}

	public static void main(String[] args) {
		new GeneArgProcessor(args).runAndOutput();
	}
}


text:
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Grouchy.HttpApi.Client.Abstractions.Extensions;
using Grouchy.HttpApi.Client.Testing;
using Grouchy.HttpApi.Client.Tests.Extensions;
using Grouchy.HttpApi.Client.Tests.Stubs;
using NUnit.Framework;
using Shouldly;

#if NET451
   using HttpContext = Microsoft.Owin.IOwinContext;
#else
   using Microsoft.AspNetCore.Http;
#endif

namespace Grouchy.HttpApi.Client.Tests.retrying_scenarios
{
   // ReSharper disable once InconsistentNaming
   public class multiple_retry_without_timeout : scenario_base
   {
      private const int ExpectedRetries = 3;

      private readonly StubHttpClientEventCallback _callback = new StubHttpClientEventCallback();

      private string _eventUri;
      private HttpResponseMessage _response;

      [OneTimeSetUp]
      public async Task setup_scenario()
      {
         using (var webApi = new PingHttpApi())
         using (var httpClient = webApi.CreateClientWithRetrying(_callback, retries: ExpectedRetries, delayMs: 10))
         {
            _eventUri = new Uri(webApi.BaseUri, "/ping").ToString();

            _response = await httpClient.GetAsync("/ping");
         }
      }

      [Test]
      public void should_log_three_attempts()
      {
         _callback.RetryAttempts.Length.ShouldBe(ExpectedRetries);
         _callback.RetryAttempts[0].Attempt.ShouldBe(1);
         _callback.RetryAttempts[1].Attempt.ShouldBe(2);
         _callback.RetryAttempts[2].Attempt.ShouldBe(3);
      }

      [Test]
      public void should_log_retry_attempt()
      {
         _callback.RetryAttempts[0].EventType.ShouldBe("HttpClientRetryAttempt");
         _callback.RetryAttempts[0].Uri.ShouldBe(_eventUri);
         _callback.RetryAttempts[0].Method.ShouldBe("GET");
      }

      [Test]
      public void should_return_status_code_400()
      {
         _response.StatusCode.ShouldBe(HttpStatusCode.BadRequest);
      }

      private class PingHttpApi : StubHttpApi
      {
         protected override async Task Handler(HttpContext context)
         {
            if (context.Request.Method == "GET" && context.Request.Path.ToString() == "/ping")
            {
               context.Response.StatusCode = 400;
            }
            else
            {
               await base.Handler(context);
            }
         }
      }
   }
}


text:
import unittest
from mock import patch, ANY
from lighter.datadog import Datadog
import lighter.main as lighter
from lighter.util import jsonRequest

class DatadogTest(unittest.TestCase):
    @patch('lighter.util.jsonRequest')
    def testNotify(self, mock_jsonRequest):
        Datadog('abc').notify(
            title='test title',
            message='test message',
            aggregation_key='/jenkins/test',
            tags=['environment:test'],
            priority='normal',
            alert_type='info')
        self.assertEquals(mock_jsonRequest.call_count, 2)
        mock_jsonRequest.assert_any_call('https://app.datadoghq.com/api/v1/events?api_key=abc', data=ANY, method='POST')
        mock_jsonRequest.assert_any_call('https://app.datadoghq.com/api/v1/series?api_key=abc', data=ANY, method='POST')

    @patch('lighter.util.jsonRequest')
    def testNoApiKey(self, mock_jsonRequest):
        Datadog('').notify(
            title='test title',
            message='test message',
            aggregation_key='/jenkins/test',
            tags=['environment:test'],
            priority='normal',
            alert_type='info')
        self.assertEquals(mock_jsonRequest.call_count, 0)

    @patch('lighter.util.jsonRequest')
    def testNoTitle(self, mock_jsonRequest):
        Datadog('abc').notify(
            title='',
            message='test message',
            aggregation_key='/jenkins/test',
            tags=['environment:test'],
            priority='normal',
            alert_type='info')
        self.assertEquals(mock_jsonRequest.call_count, 0)

    @patch('lighter.util.jsonRequest')
    def testNoMessage(self, mock_jsonRequest):
        Datadog('abc').notify(title='test title', message='', aggregation_key='/jenkins/test', tags=['environment:test'], priority='normal', alert_type='info')
        self.assertEquals(mock_jsonRequest.call_count, 0)

    @patch('lighter.util.jsonRequest')
    def testNoID(self, mock_jsonRequest):
        Datadog('abc').notify(title='test title', message='test message', aggregation_key='', tags=['environment:test'], priority='normal', alert_type='info')
        self.assertEquals(mock_jsonRequest.call_count, 0)

    def _createJsonRequestWrapper(self, marathonurl='http://localhost:1'):
        appurl = '%s/v2/apps/myproduct/myservice' % marathonurl

        def wrapper(url, method='GET', data=None, *args, **kwargs):
            if url.startswith('file:'):
                return jsonRequest(url, data, *args, **kwargs)
            if url == appurl and method == 'PUT' and data:
                return {}
            if url == appurl and method == 'GET':
                return {'app': {}}
            return None
        return wrapper

    def testDefaultTags(self):
        with patch('lighter.util.jsonRequest', wraps=self._createJsonRequestWrapper()) as mock_jsonRequest:
            lighter.deploy('http://localhost:1/', filenames=['src/resources/yaml/integration/datadog-default-tags.yml'])
            mock_jsonRequest.assert_any_call('https://app.datadoghq.com/api/v1/events?api_key=abc', data=ANY, method='POST')

            expected = [
                'environment:default',
                u'service:/myproduct/myservice',
                'source:lighter',
                'type:change']
            self.assertEquals(expected, mock_jsonRequest.call_args[1]['data']['tags'])

    def testConfiguredTags(self):
        with patch('lighter.util.jsonRequest', wraps=self._createJsonRequestWrapper()) as mock_jsonRequest:
            lighter.deploy('http://localhost:1/', filenames=['src/resources/yaml/integration/datadog-config-tags.yml'])
            mock_jsonRequest.assert_any_call('https://app.datadoghq.com/api/v1/events?api_key=abc', data=ANY, method='POST')

            expected = [
                'environment:default',
                u'service:/myproduct/myservice',
                'somekey:someval',
                'anotherkey:anotherval',
                'justakey',
                'source:lighter',
                'type:change']
            self.assertEquals(expected, mock_jsonRequest.call_args[1]['data']['tags'])

    def testDeploymentMetric(self):
        with patch('lighter.util.jsonRequest', wraps=self._createJsonRequestWrapper()) as mock_jsonRequest:
            lighter.deploy('http://localhost:1/', filenames=['src/resources/yaml/integration/datadog-config-tags.yml'])
            mock_jsonRequest.assert_any_call('https://app.datadoghq.com/api/v1/series?api_key=abc', data=ANY, method='POST')

            tags = [
                'environment:default',
                u'service:/myproduct/myservice',
                'somekey:someval',
                'anotherkey:anotherval',
                'justakey',
                'source:lighter',
                'type:change',
                'status:success']
            data = mock_jsonRequest.call_args_list[-2][1]['data']['series'][0]
            self.assertEquals('datadog.events', data['metric'])
            self.assertEquals(1, data['points'][0][1])
            self.assertEquals(tags, data['tags'])


text:
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.drools.workshop.food.endpoint.api;

import javax.validation.constraints.NotNull;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.drools.workshop.food.endpoint.exception.BusinessException;
import org.drools.workshop.food.model.Meal;
import org.drools.workshop.food.model.Person;

/**
 *
 * @author salaboy
 */
@Path("food")
public interface FoodRecommendationService {

    @POST
    @Path("")
    @Consumes(value = MediaType.APPLICATION_JSON)
    @Produces(value = MediaType.APPLICATION_JSON)
    public Meal recommendMeal(@NotNull Person person) throws BusinessException;

}


text:
<?xml version="1.0"?>

<!DOCTYPE suppressions PUBLIC
    "-//Puppy Crawl//DTD Suppressions 1.0//EN"
    "http://www.puppycrawl.com/dtds/suppressions_1_0.dtd">
<suppressions>
    <suppress checks="IllegalCatchCheck" files="StorageBase.java" />
    <suppress checks="IllegalCatchCheck" files="PiOpsUserDetailsService.java" />
    <suppress checks="ClassFanOutComplexity" files="ApplicationsController.java" />
</suppressions>


text:
module Recipe

  attr_accessor :stack

  def change_binding binding
    @binding = binding
  end

  def init binding
    change_binding binding
    stack
  end

  def resource_not_supported *args
    Output.warn 'Resource not supported', args.inspect
  end

  def clean_stack!
    @stack = []
  end

  def cron_append object
    @cron_jobs << object
    Output.info 'Cron job detected', object.get_title
  end

  def cron_variable title, variable
    @cron_jobs ||= []
    @cron_vars ||= []
    @cron_vars << ''
    @cron_vars << "# #{title}"
    @cron_vars << variable
  end

  def setup_crontab
    Output.jump
    Output.info 'Setting up nice cron jobs', 'this is sweeet root crontab!'
    Output.ruler
    t = ::Tempfile.new('temporal_crontab')
    @cron_vars.each do |line|
      t.puts line
    end
    @cron_jobs.each do |resource|
      t.puts ''
      t.puts "# #{resource.get_title}"
      t.puts "#{resource.run}"
    end
    t.close
    system "cat #{t.path} | crontab"
    system 'crontab -l'
    t.unlink
  end

  def stack
    @stack ||= []
  end

  def stack_append object
    @stack << object
  end

  def template name, &block
    stack_append ::Resource::Template.new(name, &block)
  end

  def directory name, &block
    stack_append ::Resource::Directory.new(name, &block)
  end

  def gem_package name, &block
    stack_append ::Resource::Gem.new(name, &block)
  end

  def package package_name, &block
    block = Proc.new {} unless block
    stack_append ::Resource::Package.new(package_name, &block)
  end

  def execute title, &block
    stack_append ::Resource::Execute.new(title, &block)
  end

  def user username, &block
    stack_append ::Resource::User.new(username, &block)
  end

  def link source, &block
    stack_append ::Resource::Link.new(source, &block)
  end

  def git repository, &block
    stack_append ::Resource::Git.new(repository, &block)
  end

  def cron title, &block
    cron_append ::Resource::Cron.new(title, &block)
  end

  def service name, &block
    stack_append ::Resource::Service.new(name, &block)
  end

  def system_group groupname, &block
    stack_append ::Resource::Group.new(groupname, &block)
  end

  def remote_file target, &block
    stack_append ::Resource::RemoteFile.new(target, &block)
  end

  def file target, &block
    stack_append ::Resource::File.new(target, &block)
  end

  def swap_release release_path, &block
    stack_append ::Resource::SwapRelease.new(release_path, &block)
  end

  def version location, &block
    stack_append ::Resource::Version.new(location, &block)
  end

  def hook target
    target = status.release_path + "/deploy/#{target}.rb"
    Resource::Hook.new(target, @binding).run
  end

  def node
    @node ||= ::Node.get
  end

  def include_recipe name
    @recipes ||= []
    if @recipes.include? name
      Output.warn 'Already loaded recipe with name', name
      return
    end
    @recipes << name
    Output.info 'Including recipe', name
    include_file :Recipe, @recipes_target % name
  end

  def include_file file_type, some_file
    unless ::File.exist? some_file
      Output.warn "#{file_type} file not found (skipping)", some_file
      return
    end
    eval(File.read(some_file), @binding)
    Output.info 'Executable units', stack.size
  end

  def load_recipes recipes_target, list
    Output.banner 'Loading', 'Instantiating recipes...'
    @recipes_target = recipes_target
    list.each { |recipe| include_recipe recipe }
  end

  def summary
    Output.banner 'Printing', 'Execution summary'
    Output.info 'Total Recipes', node[:recipes].size
    Output.info 'Total executable stack units', stack.size
  end

  def status
    Status.get
  end

  def transaction &block
    yield
  rescue => e
    Output.error 'Rolling back', ' =:D '
    raise e
  end

  def whoami
    (File.exist? 'env/whoami') ? File.read('env/whoami').chop : 'Unknown user'
  end

  def server_ip_address
    (File.exist? 'env/ip') ? File.read('env/ip').chop : 'Unknown ip address'
  end

end


text:
<!DOCTYPE html>

    <link href="css/reset.css" rel="stylesheet" />

    <meta charset="utf-8" />
    <meta name="viewport" content="width=1024" />
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <link rel="shortcut icon" href="css/favicon.png" />
    <link rel="apple-touch-icon" href="css/apple-touch-icon.png" />

<link href="css/highlight.css" type="text/css" rel="stylesheet" />

    <link href="css/style.css" rel="stylesheet" />
<link href='http://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,800italic,300,400,800' rel='stylesheet' type='text/css'>

Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

For the best experience please use the latest Chrome, Safari or Firefox browser.

Conversion from Instruction to MachineInstruction

IR -> SelectionDag -> X86TargetLowering [legalize dag operations w.r.t
target ] -> SelectionDAGISel(manual
implementation) || X86FastIsel ->
InstrEmitter:EmitMachineNode[ emit MachineInstructions ] ->
X86DAGToDAGISel::Select[ Register Allocation] ->
X86AsmPrinter::EmitInstruction

Removing instructions

Target Independent

eraseFromParent()

llvm/lib/CodeGen/CodeGenPrepare.cpp

// Build a truncate instruction.

truncation due to casting may lead to deletion of original instruction.
it has an undo method, which erases the instruction

Codegen preparation. Common to all architectures.
We may loose instruction information here.

// OptimizeCmpExpression - sink the given CmpInst
// into user blocks to reduce
// the number of virtual reduce registers
// that must be created and

OptimizeCmpExpression(CmpInst *CI) {}

OptimizeNoopCopyExpression -
if the specified cast instruction is Noop copy
(e.g, copy from one pointer type to another, i32->i8)
Also adds another

CodeGenPrepare::DupRetToEnableTailCallOpts(BasicBlock *BB)

Look for opportunities to duplicate return
 instructions to the predecessor to enable tail call optimizations.

/// bb0:
///   %tmp0 = tail call i32 @f0()
///   br label %return
/// bb1:
///   %tmp1 = tail call i32 @f1()
///   br label %return
/// return:
///   %retval = phi i32 [ %tmp0, %bb0 ], [ %tmp1, %bb1 ], [ %tmp2, %bb2 ]
///   ret i32 %retval

/// bb0:
///   %tmp0 = tail call i32 @f0()
///   ret i32 %tmp0
/// bb1:
///   %tmp1 = tail call i32 @f1()
///   ret i32 %tmp1

CodeGenPrepare::DupRetToEnableTailCallOpts(BasicBlock *BB)

// Duplicate the return into CallBB.
(void)FoldReturnIntoUncondBranch(RI, BB, CallBB);

TypePromotion

creates a truncated instruction

TruncBuilder(Instruction *Opnd, Type *Ty) : TypePromotionAction(Opnd) {}

class SExtBuilder : public TypePromotionAction {}

// a = b==b ? 2 : 3 -> if(b==b) 2 else 3

CodeGenPrepare::OptimizeSelectInst(SelectInst *SI) {}

// Some targets have expensive vector shifts if the lanes aren't all
the same
// (e.g. x86 only introduced "vpsllvd" and friends with AVX2). In
these cases
// it's often worth sinking a ShuffleVectorInstr splat down to its
use so that
// codegen can spot all lanes aren identical.

bool CodeGenPrepare::OptimizeShuffleVectorInst(ShuffleVectorInst *SVI) {}

X86/X86FastISel.cpp

X86InstrInfo.cpp

bool X86InstrInfo::AnalyzeBranch{}

Two eraseFromParent:
1. If the block has any instructions after a JMP, delete them. => dead code.
2. Delete the JMP if it's equivalent to a fall-through. //jmp not required.

Question: can we even instrument this.

only modifies jump instructions which can't even

jCC L1
jmp L2

we could also instrument how many times a particular branch is taken.
This transformation may potentially interfere with that.

optimizeCompareInstr

Check if an instruction already performs the same compare.

optimizeLoadInstr

This may effect the instrumentation

// Try to remove the load by folding it to a register
// operand at  the use. We fold the load instructions if load
// defines a virtual
// register, the virtual register is used once in the same BB,
// instructions in-between do not load or store, and have no side
// effects.

X86ISelLowering.cpp

MachineBasicBlock *EmitXBegin;

// Utility function to emit xbegin specifying the start of an RTM region
// RTM - restricted transactional memory

deletes the previous instruction to insert

I don't think what's the point of intrumenting some instructions.

EmitAtomicLoadArith - emit the code sequence for pseudo atomic
instructions.

EmitAtomicLoadArith6432

EmitPCMPSTRM

// When we get size specific XMM0 registers, i.e. XMM0_V16I8
// or XMM0_V32I8 in AVX all of this code can be replaced withth
// that
// in the .td file.file


text:
package com.dianyitech.madaptor.contacts.views;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.widget.ListView;
import com.dianyitech.madaptor.contacts.adapter.InternalPersonListAdapter;
import com.dianyitech.madaptor.contacts.pojo.PersonBean;
import java.util.List;

public class InternalPersonListView extends ListView
{
  private static final String TAG = "InternalPersonListView";
  private InternalPersonListAdapter adapter;
  private List<PersonBean> personList;

  public InternalPersonListView(Context paramContext)
  {
    super(paramContext);
  }

  public InternalPersonListView(Context paramContext, List<PersonBean> paramList)
  {
    super(paramContext);
    this.personList = paramList;
    setDivider(getResources().getDrawable(2130837704));
    this.adapter = new InternalPersonListAdapter(paramContext, paramList);
    setCacheColorHint(Color.alpha(0));
    setAdapter(this.adapter);
  }

  public List<PersonBean> getPersonList()
  {
    return this.personList;
  }

  public void setPersonList(List<PersonBean> paramList)
  {
    this.personList = paramList;
  }
}

/* Location:           /Users/zqq/Downloads/??????è½?ä»? 2/classes.jar
 * Qualified Name:     com.dianyitech.madaptor.contacts.views.InternalPersonListView
 * JD-Core Version:    0.6.2
 */