text:
CS 106A Style Guide

	These are the general Java style qualities that we expect your programs to have in order to receive full credit.
	Certainly it is possible to write good code that violates these guidelines, and you may feel free to contact us if you are unclear about or disagree with some of them.
	But we do expect you to follow these rules (unless there is an error in this document).
	In most professional work environments you are expected to follow that company's style standards.
	Learning to carefully obey a style guide, and writing code with a group of other developers where the style is consistent among them, are valuable job skills.

	Oracle/Sun's Official Java Coding Conventions are a more comprehensive guide to proper Java programming.
	The practices outlined on their web site are encouraged for use in CS 106A.

	This document is a work in progress.

	Last updated Sun 2017/04/02

		Whitespace and Indentation

		Naming

		Methods

		Java Control Statements

		Comments

		Forbidden Java Features

Week1 Wed 12:00 PM

Homework 1 (Karel the Robot) Style Guide

		Whitespace and Indentation

Indenting: Increase your indentation by one increment on each brace {, and decrease it once on each closing brace }.

Always use {} on control statements: With Java's control statements such as if and for, the {} braces are technically optional if the body of the control statement contains only a single line.  Regardless of this, always use the {} braces.  Always.

// bad
if (beepersPresent())
    pickBeeper();

// good
if (beepersPresent()) {
    pickBeeper();
}

Place a line break after every { .

// bad
if (beepersPresent()) { pickBeeper(); }

// good
if (beepersPresent()) {
    pickBeeper();
}

Do not place more than one statement on the same line.

// bad
move();  move();  pickBeeper();

// good
move();
move();
pickBeeper();

Long lines: Avoid lines longer than 100 characters.
				In HW1 this would most likely be a comment line.
				When you have a long line, break it into two shorter lines.

Blank lines: Place a blank line between methods and between groups of statements.

public void foo() {
    ...
}
                          // this blank line here
public void bar() {
    ...
}

		Naming

Names: Give methods descriptive names, such as walkToEdge or grabAllBeepers.
				Avoid one-letter names or non-descriptive names, like x or go or method1.

Capitalization: Name methods with camel-casing likeThis, and name classes with Pascal casing LikeThis.

(HW1) Do not use variables: In a Karel program, you should not use Java features that are not covered in the Karel reader.  Specifically, do not use variables, nor private "fields", nor "instance variables".

// bad
int steps = 42;

private int count = 0;   // bad

		Methods

run as a concise summary: As much as possible, avoid directly calling Karel commands like move in your program's run method.  Instead, have run call other methods that perform the functionality.  In this way, run is easy to read and forms a concise summary of the overall behavior of the program.

Minimize redundant code: If you repeat the same code two or more times, find a way to remove the redundant code so that it appears only once.
				For example, you can place it into a method that is called from both places.

Long methods: If you have a single method that is very long, break it apart into smaller sub-methods.
				The definition of "very long" is vague, but let's say a method longer than 20-30 lines is pushing it.
				If you try to describe the method's purpose and find yourself using the word "and" a lot, that probably means the method does too many things and should be split into sub-methods.

Short methods: It is not useful to make a method that only calls one other existing Karel method.  But it can be useful to have a short method if, say, it wraps another method in an if/else statement in a way that is commonly used.

// bad
public void makeLeftTurn() {
    turnLeft();
}

// good
public void safePickup() {
    if (beepersPresent()) {
        pickBeeper();
    }
}

Mutual recursion: Recursion (which you'll learn about in CS 106B/X) is when methods call themselves.  Mutual recursion is where you have two methods that each call the other to form a cycle of calls.  In CS 106A assignments, mutual recursion is generally a bad algorithmic strategy that should be avoided.  In many cases the mutual recursion is being used to avoid a more appropriate usage of a for or while loop.

// bad
public void methodOne() {
    if (frontIsClear()) {
        move();
        methodTwo();
    }
}

public void methodTwo() {
    if (frontIsClear()) {
        move();
        methodOne();
    }
}

// good
public void methodOne() {
    while (frontIsClear()) {
        move();
    }
}

		Java Control Statements

avoid empty if or else: When using if/else statements, don't ever have an if or else branch that is blank.  Rephrase your test to avoid this.

// bad
if (frontIsBlocked()) {
    // do nothing

} else {
    move();
}

// good
if (frontIsClear()) {
    move();
}

for vs while: Use a for loop when the number of repetitions is known (definite); use a while loop when the number of repetitions is unknown (indefinite).

// repeat until the front is blocked
// (works for worlds up to size 1000)
for (int i = 0; i < 1000; i++) {
    if (frontIsClear()) {
        ...
    }
}

// repeat exactly 10 times
for (int i = 0; i < 10; i++) {
    ...
}

// repeat until the front is blocked
while (frontIsClear()) {
    ...
}

(HW1+) break and continue:
					The break or continue statements in loops should not be used on the assignment.

if/else factoring: Move common code out of if/else statements so that it is not redundantly repeated.

// bad
if (beepersPresent()) {
    move();
    pickBeeper();
    move();
    turnLeft();
    turnLeft();
    move();
} else {
    move();
    move();
    turnLeft();
    turnLeft();
    move();
}

// good
move();
if (beepersPresent()) {
    pickBeeper();
}
move();
turnLeft();
turnLeft();
move();

infinite loops: Avoid writing loops that never stop, such as the following.  An infinite loop will cause your program to never stop executing.  Replace an infinite loop with a loop that does terminate.

// bad
while (leftIsClear()) {
    if (frontIsClear()) {
        move();
    }
}

// good
while (frontIsClear()) {
    move();
}

		Comments

Class header: Place a descriptive comment heading on the top of every file describing that file's purpose.
				Assume that the reader of your comments is an intelligent programmer but not someone who has seen this assignment before.
				Your comment header should include at least your name, course/section, and a brief description of that assignment or file.
				If the assignment asks you to submit multiple files, each file's comment header should describe that file/class and its main purpose in the program.

Method headers: Place a comment heading on each method of your class.
				The heading should describe the method's behavior.

Pre/Postconditions: If your method makes any assumptions (preconditions), mention this in your comments.  If it leaves the program in a certain state when it is done (postcondition), mention this as well.

Inline comments: Inside the interiors of your various methods, if you have sections of code that are lengthy or complex or non-trivial, place a small amount of inline comments near these lines of complex code describing what they are doing.

Implementation details: Comment headers at the top of a method or class should describe the method's behavior, but not great detail about how it is implemented.  Do not mention language-specific details like the fact that the method uses a if/else statement, that the method declares an array, that the method loops over a collection and counts various elements, etc.

No trivial comments: Do not make obvious comments about the meaning of individual statements.  You should assume that the reader is familiar with Karel and Java in general.

// bad
turnLeft();     // turns Karel counter clockwise

move();         // this tells Karel to move forward

Wording: Your comment headers should be written in complete sentences, and should be written in your own words, not copied from other sources (such as copied verbatim from the homework spec document).

TODOs: You should remove any // TODO: comments from a program before turning it in.

Commented-out code: It is considered bad style to turn in a program with chunks of code "commented out".  It's fine to comment out code as you are working on a program, but if the program is done and such code is not needed, just remove it.

			Here is a decent overall example of a good comment header on a method.  Not every comment header needs to be this long, but since this method takes a parameter and returns something, it needs to mention several things.

/*
 * Jumps Karel over one hurdle of arbitrary height by walking north over it,
 * and then back down to his original row.
 * Pre:  Karel is next to a jumpable hurdle, facing east.
 * Post: Karel will be over the hurdle, one column to the right, facing east.
 */
public void jumpHurdle() {
    ...
}

		(HW1) Forbidden Java Features

Variables: On a Karel program, you must limit yourself to the Java features shown in the Karel reader document.  In particular, you should not use variables such as the following.

// bad (on HW1)
int steps = 42;
while (steps > 0) {
	move();
	turnLeft();
	steps = steps - 1;
}

Data fields: These are the 'private' data variables that are declared outside of methods.  These are just another form of variables and should not be used on HW1.

// bad (on HW1)
public class MyKarel extends Karel {
    private int count;   // bad bad bad

    public void run() {
        count = 5;
        ...
    }
}

Infinite loops: One loop style, sometimes used as a way to fix a fencepost problem, is to use what is called an 'infinite loop' or a 'while true loop' with a break statement.  This is not shown in the Karel reader and is not permitted on HW1.

// bad (on HW1)
while (true) {
    if (frontIsClear()) {
        move();
    } else {
        break;
    }
}

Parameters: Java methods are able to accept parameters that affect their behavior.  This is not shown in the Karel reader and is not permitted on HW1.  Returning a value from a method (non-void) is similarly forbidden.

// bad (on HW1)
public void walk(int numSteps) {
    for (int i = 0; i < numSteps; i++) {
        move();
    }
}

Other Java features: In general, you should not use any Java features on HW1 that are not in the Karel Learns Java document.  There are too many features to list them all, but in general you should match the Java features used in the sample programs in class and in the Karel reader and not use any Java features outside of those ones.

		(HW2+) New Style Guidelines

Variable types: Choose appropriate data types for your variables.
				If a given variable can store only integers, give it type int rather than double.

Variable scope: Declare variables in the narrowest possible scope.
				For example, if a variable is used only inside a specific if statement, declare it inside that if statement rather than at the top of the method or at the top of the file.

Variable declaration/initialization: Never declare or initialize more than one variable in a single statement.

// bad
int a = 7, b = -43, c = 19;

// good
int a = 7;
int b = -43;
int c = 19;

Constants: If a particular constant value is used frequently in your code, declare it as a final constant, and always refer to the constant in the rest of your code rather than referring to the corresponding value.
					Name final constants in uppercase with underscores between words LIKE_THIS.

private static final int VOTING_AGE = 18;

if/else patterns: When using if/else statements, properly choose between various if and else patterns depending on whether the conditions are related to each other.  Avoid redundant or unnecessary if tests.

// bad
if (grade >= 90) {
    println("You got an A!");
}
if (grade >= 80 && grade < 90) {
    println("You got a B!");
}
if (grade >= 70 && grade < 80) {
    println("You got a C!");
}
...

// good
if (grade >= 90) {
    println("You got an A!");
} else if (grade >= 80) {
    println("You got a B!");
} else if (grade >= 70) {
    println("You got a C!");
}
...

Minimize redundant code: If you repeat the same code two or more times, find a way to remove the redundant code so that it appears only once.
				For example, place it into a helper function that is called from both places.
				If the repeated code is nearly but not entirely the same, try making your helper function accept a parameter to represent the differing part.

// bad
foo();
x = 10;
y++;
...

foo();
x = 15;
y++;

// good
helper(10);
helper(15);
...

void helper(int newX) {
    foo();
    x = newX;
    y++;
}

break and continue:
					In general, you should avoid using the break or continue statements in loops unless absolutely necessary.
					A break can often be avoided by rewriting the loop test or reordering the statements in/near the loop.

System.exit(): Java contains a System.exit method that immediately exits your entire program.
				You should never call this method in our assignments for any reason.
				Your program should always exit naturally by reaching the end of your run function and returning.

Boolean zen 1: If you have an if/else statement that returns a boolean value based on a test, just directly return the test's result instead.

// bad
if (score1 == score2) {
    return true;
} else {
    return false;
}

// good
return score1 == score2;

Boolean zen 2: Don't ever test whether a boolean value is == or != to true or false.

// bad
if (x == true) {
    ...
} else if (x != true) {
    ...
}

// good
if (x) {
    ...
} else {
    ...
}

					Save expensive call results in a variable:
					If you are calling an expensive method and using its result multiple times, save that result in a variable rather than having to call the method multiple times.

// bad
if (list.indexOf("abc") >= 0) {
    list.remove(list.indexOf("abc"));
}

// good
int index = list.indexOf("abc");
if (index >= 0) {
    list.remove(index);
}

Exception handling: Don't ever catch an exception with an empty catch block.

// bad
try {
    foo();
    bar();
} catch (NullPointerException e) {}

Also, don't use try/catch as a kludge to cover up an error that your program is generating.
					Debug and sidestep the error to prevent it from happening instead.

// bad
try {
    myFunctionThatCrashesForSomeReason();
} catch (IndexOutOfBoundsException e) {
    // LOL no crash now
}

Similarly, don't ever catch (Exception) unless told explicitly to do so, because this is overly inclusive and will suppress important system error messages.
					You should instead catch a more specific subcategory of exceptions such as IOException or SocketException.

// bad
try {
    foo();
    bar();
} catch (Exception e) {}

		(Later Assignments) Class Design

Properly encapsulate your objects by making any data fields in your class private.

public class Student {
    private int homeworkScore;
    ...

Avoid unnecessary fields; use fields to store important data of your objects but not to store temporary values only used within a single call to one method.

Initialize fields in constructors, not where they are declared.

public class Student {
    private int homeworkScore = 10;
    private int homeworkScore;

    public Student() {
        homeworkScore = 10;
    }

Avoid empty zero-argument constructors.  If you don't need to do anything to initialize your object, just omit the constructor.

public class Student {
    ...
    public Student() {}
}

Helper methods: If you add a method to a class that is not part of the homework spec, make it private so that other external code cannot call it.

public class Student {
    ...
    private double computeTuitionHelper() {
        ...
    }

Instance vs. static: A static member of a class is a single occurrence shared by that class and all of its objects.
					An instance member is one that is replicated into each object of that class.
					When designing your class, any data that should be individual to each object should be non-static.
					This still holds even if the assignment's client program only happens to construct one object of your class.

public class Student {
    private static int homeworkScore;   // all students share one homework score (bad)
    private int homeworkScore;          // each student has his own homework score (good)

    public Student() {
        homeworkScore = 10;
    }


text:
import { Component, Input, Output, OnInit } from '@angular/core';

/**
 * Empty parent component for inheritance demo
 */
@Component({
    selector: 'empty-parent',
    template: 'empty parent'
})
export class EmptyParentComponent implements OnInit {
    @Input() public parentInput: string;

    @Output() public parentoutput;

    public parentProperty;

    ngOnInit() {}
}

redpajama_set_name: RedPajamaGithub


text:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.zl.test</groupId>
    <artifactId>spring-cloud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>zuul</artifactId>
      <dependencyManagement>
  	<dependencies>
  		<dependency>
  			<groupId>org.springframework.cloud</groupId>
  			<artifactId>spring-cloud-dependencies</artifactId>
  			<version>Camden.SR2</version>
  			<type>pom</type>
  			<scope>import</scope>
  		</dependency>
  	</dependencies>
  </dependencyManagement>
      <dependencies>
      	<dependency>
      		<groupId>org.springframework.cloud</groupId>
      		<artifactId>spring-cloud-starter-zuul</artifactId>
      	</dependency>
      	<dependency>
      		<groupId>org.springframework.cloud</groupId>
      		<artifactId>spring-cloud-starter-hystrix</artifactId>
      	</dependency>
      	<dependency>
      		<groupId>org.springframework.cloud</groupId>
      		<artifactId>spring-cloud-starter-eureka</artifactId>
      	</dependency>
      </dependencies>
</project>


text:
module Airbrake
  module Rails
    module ControllerMethods

      def airbrake_request_data
        {
          :parameters       => airbrake_filter_if_filtering(params.to_hash),
          :session_data     => airbrake_filter_if_filtering(airbrake_session_data),
          :controller       => params[:controller],
          :action           => params[:action],
          :url              => airbrake_request_url,
          :cgi_data         => airbrake_filter_if_filtering(request.env),
          :user             => airbrake_current_user
        }
      end

      private

      # This method should be used for sending manual notifications while you are still
      # inside the controller. Otherwise it works like Airbrake.notify.
      def notify_airbrake(hash_or_exception)
        unless airbrake_local_request?
          Airbrake.notify_or_ignore(hash_or_exception, airbrake_request_data)
        end
      end

      def airbrake_local_request?
        if defined?(::Rails.application.config)
          ::Rails.application.config.consider_all_requests_local || (request.local? && (!request.env["HTTP_X_FORWARDED_FOR"]))
        else
          consider_all_requests_local || (local_request? && (!request.env["HTTP_X_FORWARDED_FOR"]))
        end
      end

      def airbrake_ignore_user_agent? #:nodoc:
        # Rails 1.2.6 doesn't have request.user_agent, so check for it here
        user_agent = request.respond_to?(:user_agent) ? request.user_agent : request.env["HTTP_USER_AGENT"]
        Airbrake.configuration.ignore_user_agent.flatten.any? { |ua| ua === user_agent }
      end

      def airbrake_filter_if_filtering(hash)
        return hash if ! hash.is_a?(Hash)

        if respond_to?(:filter_parameters) # Rails 2
          filter_parameters(hash)
        elsif rails3?
          filter_rails3_parameters(hash)
        else
          hash
        end
      end

      def rails3?
        defined?(::Rails.version) && ::Rails.version =~ /\A3/
      end

      def filter_rails3_parameters(hash)
        ActionDispatch::Http::ParameterFilter.new(
          ::Rails.application.config.filter_parameters).filter(hash)
      end

      def airbrake_session_data
        if session
          if session.respond_to?(:to_hash)
            session.to_hash
          else
            session.data
          end
        else
          {:session => 'no session found'}
        end
      end

      def airbrake_request_url
        url = "#{request.protocol}#{request.host}"

        unless [80, 443].include?(request.port)
          url << ":#{request.port}"
        end

        url << request.fullpath
        url
      end

      def airbrake_current_user
        user = begin current_user rescue current_member end
        h = {}
        return h if user.nil?
        Airbrake.configuration.user_attributes.map(&:to_sym).each do |attr|
          h[attr.to_sym] = user.send(attr) if user.respond_to? attr
        end
        h
      rescue NoMethodError, NameError
        {}
      end
    end
  end
end


text:
using System;

namespace bstrkr.core.services.animation
{
    public class PositionAnimationPlaybackEventArgs : EventArgs
    {
        public PositionAnimationPlaybackEventArgs(PathSegment segment)
        {
            this.PathSegment = segment;
        }

        public PathSegment PathSegment { get; private set; }
    }
}


text:
package com.wentam.defcol.paletteList;

import com.wentam.defcol.R;
import com.wentam.defcol.PaletteFile;
import com.wentam.defcol.palette.PaletteActivity;

import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;

import android.widget.BaseAdapter;
import android.widget.TextView;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ListView;

import android.content.Context;
import android.content.Intent;

import java.util.ArrayList;
import android.util.Log;

public class PaletteListAdapter extends BaseAdapter {
    private LayoutInflater layoutInflater;
    private ArrayList<String> items;
    private PaletteFile paletteFile;
    private PaletteListAdapter me;
    private Context context;
    private ListView lv;

    // --
    // listeners
    // --

     OnClickListener mainListener = new OnClickListener() {
    	    @Override
    	    public void onClick(View v) {
    		int position = (Integer) v.getTag();

		if (lv.getCheckedItemCount() > 0) {
		    if (lv.isItemChecked(position)) {
			lv.setItemChecked(position, false);
		    } else {
			lv.setItemChecked(position, true);
		    }
		} else {
		    Intent intent = new Intent(me.context, PaletteActivity.class);
		    intent.putExtra("pallete_id",""+position);
		    int[] tmp = {1};
		    intent.putExtra("pallete_colors",""+me.paletteFile.getRow(position, tmp));
		    me.context.startActivity(intent);
		}
    	    }
    	};

    OnLongClickListener longPress = new OnLongClickListener() {
	    @Override
	    public boolean onLongClick(View v) {
		int position = (Integer) v.getTag();

		if (lv.isItemChecked(position)) {
		    lv.setItemChecked(position, false);
		} else {
		    lv.setItemChecked(position, true);
		}
		return true;
	    }
	};

    // --
    // constructor
    // --

    public PaletteListAdapter(Context c, ArrayList<String> i, PaletteFile p, ListView l) {
	super();

	this.layoutInflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
	this.items = i;
	this.paletteFile = p;
	this.me = this;
	this.context = c;
	this.lv = l;
    }

    // --
    // methods
    // --

    public View getView (int position, View convertView, ViewGroup parent) {
	ImageButton delete_btn;
	Button main_btn;

	if (convertView == null) {
	    convertView = layoutInflater.inflate(R.layout.palette_list_item, null);

	    main_btn = ((Button) convertView.findViewById(R.id.main_btn));
	    main_btn.setTag(position);
	    main_btn.setOnClickListener(mainListener);
	    main_btn.setOnLongClickListener(longPress);
	} else {

	    main_btn = ((Button) convertView.findViewById(R.id.main_btn));
	    main_btn.setTag(position);
	}

	((TextView) convertView.findViewById(R.id.textview)).setText(items.get(position));

	return convertView;
    }

    public int getCount() {
	return this.items.size();
    }

    public long getItemId (int position) {
	return position;
    }

    public Object getItem (int position) {
	return this.items.get(position);
    }
}


text:
import {Services} from '../services';
import {createCustomEvent} from '../event-helper.js';
import {whenContentIniLoad} from '../ini-load';

/**
 * Registers ini-load listener that will fire custom 'amp-ini-load' event
 * on window (accessible if creative is friendly to ad tag) and postMessage to
 * window parent.
 * @param {!../service/ampdoc-impl.AmpDoc} ampdoc
 */
export function registerIniLoadListener(ampdoc) {
  const {win} = ampdoc;
  const root = ampdoc.getRootNode();
  whenContentIniLoad(
    ampdoc,
    win,
    Services.viewportForDoc(ampdoc).getLayoutRect(
      root.documentElement || root.body || root
    )
  ).then(() => {
    win.dispatchEvent(
      createCustomEvent(win, 'amp-ini-load', /* detail */ null, {bubbles: true})
    );
    if (win.parent) {
      win.parent./*OK*/ postMessage('amp-ini-load', '*');
    }
  });
}

/**
 * Function to get the amp4ads-identifier from the meta tag on the document
 * @param {!Window} win
 * @return {?string}
 */
export function getA4AId(win) {
  const a4aIdMetaTag = win.document.head.querySelector(
    'meta[name="amp4ads-id"]'
  );

  if (a4aIdMetaTag) {
    return a4aIdMetaTag.getAttribute('content');
  }

  return null;
}


text:
module TestUnit
  module Generators
    class DecoratorGenerator < ::Rails::Generators::NamedBase
      source_root File.expand_path("templates", __dir__)
      check_class_collision suffix: "DecoratorTest"

      def create_test_file
        template 'decorator_test.rb', File.join('test/decorators', class_path, "#{file_name}_decorator_test.rb")
      end
    end
  end
end


text:
package org.robolectric.shadows;

import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import static org.robolectric.Shadows.shadowOf;

import android.webkit.JsResult;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.TestRunners;
import org.robolectric.shadow.api.Shadow;

@RunWith(TestRunners.MultiApiSelfTest.class)
public class ShadowJsResultTest {

  @Test
  public void shouldRecordCanceled() throws Exception {
    JsResult jsResult = Shadow.newInstanceOf(JsResult.class);

    assertFalse(shadowOf(jsResult).wasCancelled());

    jsResult.cancel();
    assertTrue(shadowOf(jsResult).wasCancelled());

  }

}


text:
package org.sunger.net.ui.activity;

import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.Display;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;

import org.sunger.net.exception.Logger;

import io.vov.vitamio.MediaPlayer;
import io.vov.vitamio.Vitamio;
import io.vov.vitamio.widget.MediaController;
import io.vov.vitamio.widget.VideoView;
import sunger.org.demo.R;

public class LocalVideoPlayerActivity extends BaseCompatActivity implements MediaPlayer.OnCompletionListener, MediaPlayer.OnInfoListener {

	private String mPath;
	private String mTitle;
	private VideoView mVideoView;
	private View mVolumeBrightnessLayout;
	private ImageView mOperationBg;
	private ImageView mOperationPercent;
	private AudioManager mAudioManager;
	/** 最大声音 */
	private int mMaxVolume;
	/** 当前声音 */
	private int mVolume = -1;
	/** 当前亮度 */
	private float mBrightness = -1f;
	/** 当前缩放模式 */
	private int mLayout = VideoView.VIDEO_LAYOUT_ZOOM;
	private GestureDetector mGestureDetector;
	private MediaController mMediaController;
	private View mLoadingView;

	@Override
	public void onCreate(Bundle bundle) {
		super.onCreate(bundle);
		// ~~~ 获取播放地址和标题
		Intent intent = getIntent();
		mPath = intent.getStringExtra("path");
		mTitle = intent.getStringExtra("title");
		if (TextUtils.isEmpty(mPath)) {
			mPath = Environment.getExternalStorageDirectory() + "/video/你太猖狂.flv";

		} else if (intent.getData() != null)
			mPath = intent.getData().toString();

		// ~~~ 绑定控件
		setContentView(R.layout.videoview);
		mVideoView = (VideoView) findViewById(R.id.surface_view);
		mVolumeBrightnessLayout = findViewById(R.id.operation_volume_brightness);
		mOperationBg = (ImageView) findViewById(R.id.operation_bg);
		mOperationPercent = (ImageView) findViewById(R.id.operation_percent);
		mLoadingView = findViewById(R.id.video_loading);

		// ~~~ 绑定事件
		mVideoView.setOnCompletionListener(this);
		mVideoView.setOnInfoListener(this);

		// ~~~ 绑定数据
		mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
		mMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
		if (mPath.startsWith("http:"))
			mVideoView.setVideoURI(Uri.parse(mPath));
		else
			mVideoView.setVideoPath(mPath);

		//设置显示名称
		mMediaController = new MediaController(this);
		mMediaController.setFileName(mTitle);
		mVideoView.setMediaController(mMediaController);
		mVideoView.requestFocus();

		mGestureDetector = new GestureDetector(this, new MyGestureListener());
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
	}

	@Override
	protected void onPause() {
		super.onPause();
		if (mVideoView != null)
			mVideoView.pause();
	}

	@Override
	protected void onResume() {
		super.onResume();
		if (mVideoView != null)
			mVideoView.resume();
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		if (mVideoView != null)
			mVideoView.stopPlayback();
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (mGestureDetector.onTouchEvent(event))
			return true;

		// 处理手势结束
		switch (event.getAction() & MotionEvent.ACTION_MASK) {
			case MotionEvent.ACTION_UP:
				endGesture();
				break;
		}

		return super.onTouchEvent(event);
	}

	/** 手势结束 */
	private void endGesture() {
		mVolume = -1;
		mBrightness = -1f;

		// 隐藏
		mDismissHandler.removeMessages(0);
		mDismissHandler.sendEmptyMessageDelayed(0, 500);
	}

	private class MyGestureListener extends SimpleOnGestureListener {

		/** 双击 */
		@Override
		public boolean onDoubleTap(MotionEvent e) {
			if (mLayout == VideoView.VIDEO_LAYOUT_ZOOM)
				mLayout = VideoView.VIDEO_LAYOUT_ORIGIN;
			else
				mLayout++;
			if (mVideoView != null)
				mVideoView.setVideoLayout(mLayout, 0);
			return true;
		}

		/** 滑动 */
		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
			float mOldX = e1.getX(), mOldY = e1.getY();
			int y = (int) e2.getRawY();
			Display disp = getWindowManager().getDefaultDisplay();
			int windowWidth = disp.getWidth();
			int windowHeight = disp.getHeight();

			if (mOldX > windowWidth * 4.0 / 5)// 右边滑动
				onVolumeSlide((mOldY - y) / windowHeight);
			else if (mOldX < windowWidth / 5.0)// 左边滑动
				onBrightnessSlide((mOldY - y) / windowHeight);

			return super.onScroll(e1, e2, distanceX, distanceY);
		}
	}

	/** 定时隐藏 */
	private Handler mDismissHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			mVolumeBrightnessLayout.setVisibility(View.GONE);
		}
	};

	/**
	 * 滑动改变声音大小
	 *
	 * @param percent
	 */
	private void onVolumeSlide(float percent) {
		if (mVolume == -1) {
			mVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
			if (mVolume < 0)
				mVolume = 0;

			// 显示
			mOperationBg.setImageResource(R.drawable.video_volumn_bg);
			mVolumeBrightnessLayout.setVisibility(View.VISIBLE);
		}

		int index = (int) (percent * mMaxVolume) + mVolume;
		if (index > mMaxVolume)
			index = mMaxVolume;
		else if (index < 0)
			index = 0;

		// 变更声音
		mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index, 0);

		// 变更进度条
		ViewGroup.LayoutParams lp = mOperationPercent.getLayoutParams();
		lp.width = findViewById(R.id.operation_full).getLayoutParams().width * index / mMaxVolume;
		mOperationPercent.setLayoutParams(lp);
	}

	/**
	 * 滑动改变亮度
	 *
	 * @param percent
	 */
	private void onBrightnessSlide(float percent) {
		if (mBrightness < 0) {
			mBrightness = getWindow().getAttributes().screenBrightness;
			if (mBrightness <= 0.00f)
				mBrightness = 0.50f;
			if (mBrightness < 0.01f)
				mBrightness = 0.01f;

			// 显示
			mOperationBg.setImageResource(R.drawable.video_brightness_bg);
			mVolumeBrightnessLayout.setVisibility(View.VISIBLE);
		}
		WindowManager.LayoutParams lpa = getWindow().getAttributes();
		lpa.screenBrightness = mBrightness + percent;
		if (lpa.screenBrightness > 1.0f)
			lpa.screenBrightness = 1.0f;
		else if (lpa.screenBrightness < 0.01f)
			lpa.screenBrightness = 0.01f;
		getWindow().setAttributes(lpa);

		ViewGroup.LayoutParams lp = mOperationPercent.getLayoutParams();
		lp.width = (int) (findViewById(R.id.operation_full).getLayoutParams().width * lpa.screenBrightness);
		mOperationPercent.setLayoutParams(lp);
	}

	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		if (mVideoView != null)
			mVideoView.setVideoLayout(mLayout, 0);
		super.onConfigurationChanged(newConfig);
	}

	@Override
	public void onCompletion(MediaPlayer player) {
		finish();
	}

	private void stopPlayer() {
		if (mVideoView != null)
			mVideoView.pause();
	}

	private void startPlayer() {
		if (mVideoView != null)
			mVideoView.start();
	}

	private boolean isPlaying() {
		return mVideoView != null && mVideoView.isPlaying();
	}

	/** 是否需要自动恢复播放,用于自动暂停,恢复播放 */
	private boolean needResume;

	@Override
	public boolean onInfo(MediaPlayer arg0, int arg1, int arg2) {
		switch (arg1) {
			case MediaPlayer.MEDIA_INFO_BUFFERING_START:
				//开始缓存,暂停播放
				if (isPlaying()) {
					stopPlayer();
					needResume = true;
				}
				mLoadingView.setVisibility(View.VISIBLE);
				break;
			case MediaPlayer.MEDIA_INFO_BUFFERING_END:
				//缓存完成,继续播放
				if (needResume)
					startPlayer();
				mLoadingView.setVisibility(View.GONE);
				break;
			case MediaPlayer.MEDIA_INFO_DOWNLOAD_RATE_CHANGED:
				//显示 下载速度
				Logger.e("download rate:" + arg2);
				//mListener.onDownloadRateChanged(arg2);
				break;
		}
		return true;
	}
}


text:
<?php

declare(strict_types=1);

namespace Chubbyphp\Tests\Deserialization\Resources\Model;

final class Model
{
    private ?string $name = null;

    private ?OneModel $one = null;

    /**
     * @var AbstractManyModel[]
     */
    private array $manies = [];

    public function getName(): string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function getOne(): ?OneModel
    {
        return $this->one;
    }

    public function setOne(?OneModel $one = null): self
    {
        $this->one = $one;

        return $this;
    }

    /**
     * @return AbstractManyModel[]
     */
    public function getManies(): array
    {
        return $this->manies;
    }

    /**
     * @param AbstractManyModel[] $manies
     */
    public function setManies(array $manies): self
    {
        $this->manies = $manies;

        return $this;
    }
}


text:
import Transition from '../Transition'

export default function (register) {
    return {
        matches: (value) => value.toUpperCase() === `(${register})`,
        extractValue: () => null,
        formatValue: () => `(${register})`,
        extraOpcodes: () => [],
        extraSize: 0,
        example: `(${register})`,
        loader: (state) => {
            const address = state.registers[register]

            return state.getMemoryByte(address)
        },
        storer: (state) => {
            const address = state.registers[register]

            return (result) => new Transition().withByteAt(address, result)
        }
    }
}


text:
package yeeYaml

// Write an achor.
func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool {
	if emitter.anchor_data.anchor == nil {
		return true
	}
	c := []byte{'&'}
	if emitter.anchor_data.alias {
		c[0] = '*'
	}
	if !yaml_emitter_write_indicator(emitter, c, true, false, false) {
		return false
	}
	return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor)
}

// Write a tag.
func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool {
	if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 {
		return true
	}
	if len(emitter.tag_data.handle) > 0 {
		if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) {
			return false
		}
		if len(emitter.tag_data.suffix) > 0 {
			if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
				return false
			}
		}
	} else {
		// [Go] Allocate these slices elsewhere.
		if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) {
			return false
		}
		if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
			return false
		}
		if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) {
			return false
		}
	}
	return true
}

// Write a scalar.
func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool {
	switch emitter.scalar_data.style {
	case yaml_PLAIN_SCALAR_STYLE:
		return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)

	case yaml_SINGLE_QUOTED_SCALAR_STYLE:
		return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)

	case yaml_DOUBLE_QUOTED_SCALAR_STYLE:
		return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)

	case yaml_LITERAL_SCALAR_STYLE:
		return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value)

	case yaml_FOLDED_SCALAR_STYLE:
		return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value)
	}
	panic("unknown scalar style")
}


text:
layout: post
title: 140
date: 2010-02-13 16:17
comments: false
categories: [aphorisms]
---

People have small imaginations, the world is pretty big.


text:
namespace boost {
namespace fibers {

enum class cv_status {
    no_timeout = 1,
    timeout
};

class BOOST_FIBERS_DECL condition_variable_any {
private:
    detail::spinlock    wait_queue_splk_{};
    wait_queue          wait_queue_{};

public:
    condition_variable_any() = default;

    ~condition_variable_any() {
        BOOST_ASSERT( wait_queue_.empty() );
    }

    condition_variable_any( condition_variable_any const&) = delete;
    condition_variable_any & operator=( condition_variable_any const&) = delete;

    void notify_one() noexcept;

    void notify_all() noexcept;

    template< typename LockType >
    void wait( LockType & lt) {
        context * active_ctx = context::active();
        // atomically call lt.unlock() and block on *this
        // store this fiber in waiting-queue
        detail::spinlock_lock lk{ wait_queue_splk_ };
        lt.unlock();
        wait_queue_.suspend_and_wait( lk, active_ctx);

        // relock external again before returning
        try {
            lt.lock();
#if defined(BOOST_CONTEXT_HAS_CXXABI_H)
        } catch ( abi::__forced_unwind const&) {
            throw;
#endif
        } catch (...) {
            std::terminate();
        }
    }

    template< typename LockType, typename Pred >
    void wait( LockType & lt, Pred pred) {
        while ( ! pred() ) {
            wait( lt);
        }
    }

    template< typename LockType, typename Clock, typename Duration >
    cv_status wait_until( LockType & lt, std::chrono::time_point< Clock, Duration > const& timeout_time_) {
        context * active_ctx = context::active();
        cv_status status = cv_status::no_timeout;
        std::chrono::steady_clock::time_point timeout_time = detail::convert( timeout_time_);
        // atomically call lt.unlock() and block on *this
        // store this fiber in waiting-queue
        detail::spinlock_lock lk{ wait_queue_splk_ };
        // unlock external lt
        lt.unlock();
        if ( ! wait_queue_.suspend_and_wait_until( lk, active_ctx, timeout_time)) {
            status = cv_status::timeout;
        }
        // relock external again before returning
        try {
            lt.lock();
#if defined(BOOST_CONTEXT_HAS_CXXABI_H)
        } catch ( abi::__forced_unwind const&) {
            throw;
#endif
        } catch (...) {
            std::terminate();
        }
        return status;
    }

    template< typename LockType, typename Clock, typename Duration, typename Pred >
    bool wait_until( LockType & lt,
                     std::chrono::time_point< Clock, Duration > const& timeout_time, Pred pred) {
        while ( ! pred() ) {
            if ( cv_status::timeout == wait_until( lt, timeout_time) ) {
                return pred();
            }
        }
        return true;
    }

    template< typename LockType, typename Rep, typename Period >
    cv_status wait_for( LockType & lt, std::chrono::duration< Rep, Period > const& timeout_duration) {
        return wait_until( lt,
                           std::chrono::steady_clock::now() + timeout_duration);
    }

    template< typename LockType, typename Rep, typename Period, typename Pred >
    bool wait_for( LockType & lt, std::chrono::duration< Rep, Period > const& timeout_duration, Pred pred) {
        return wait_until( lt,
                           std::chrono::steady_clock::now() + timeout_duration,
                           pred);
    }
};

class BOOST_FIBERS_DECL condition_variable {
private:
    condition_variable_any      cnd_;

public:
    condition_variable() = default;

    condition_variable( condition_variable const&) = delete;
    condition_variable & operator=( condition_variable const&) = delete;

    void notify_one() noexcept {
        cnd_.notify_one();
    }

    void notify_all() noexcept {
        cnd_.notify_all();
    }

    void wait( std::unique_lock< mutex > & lt) {
        // pre-condition
        BOOST_ASSERT( lt.owns_lock() );
        BOOST_ASSERT( context::active() == lt.mutex()->owner_);
        cnd_.wait( lt);
        // post-condition
        BOOST_ASSERT( lt.owns_lock() );
        BOOST_ASSERT( context::active() == lt.mutex()->owner_);
    }

    template< typename Pred >
    void wait( std::unique_lock< mutex > & lt, Pred pred) {
        // pre-condition
        BOOST_ASSERT( lt.owns_lock() );
        BOOST_ASSERT( context::active() == lt.mutex()->owner_);
        cnd_.wait( lt, pred);
        // post-condition
        BOOST_ASSERT( lt.owns_lock() );
        BOOST_ASSERT( context::active() == lt.mutex()->owner_);
    }

    template< typename Clock, typename Duration >
    cv_status wait_until( std::unique_lock< mutex > & lt,
                          std::chrono::time_point< Clock, Duration > const& timeout_time) {
        // pre-condition
        BOOST_ASSERT( lt.owns_lock() );
        BOOST_ASSERT( context::active() == lt.mutex()->owner_);
        cv_status result = cnd_.wait_until( lt, timeout_time);
        // post-condition
        BOOST_ASSERT( lt.owns_lock() );
        BOOST_ASSERT( context::active() == lt.mutex()->owner_);
        return result;
    }

    template< typename Clock, typename Duration, typename Pred >
    bool wait_until( std::unique_lock< mutex > & lt,
                     std::chrono::time_point< Clock, Duration > const& timeout_time, Pred pred) {
        // pre-condition
        BOOST_ASSERT( lt.owns_lock() );
        BOOST_ASSERT( context::active() == lt.mutex()->owner_);
        bool result = cnd_.wait_until( lt, timeout_time, pred);
        // post-condition
        BOOST_ASSERT( lt.owns_lock() );
        BOOST_ASSERT( context::active() == lt.mutex()->owner_);
        return result;
    }

    template< typename Rep, typename Period >
    cv_status wait_for( std::unique_lock< mutex > & lt,
                        std::chrono::duration< Rep, Period > const& timeout_duration) {
        // pre-condition
        BOOST_ASSERT( lt.owns_lock() );
        BOOST_ASSERT( context::active() == lt.mutex()->owner_);
        cv_status result = cnd_.wait_for( lt, timeout_duration);
        // post-condition
        BOOST_ASSERT( lt.owns_lock() );
        BOOST_ASSERT( context::active() == lt.mutex()->owner_);
        return result;
    }

    template< typename Rep, typename Period, typename Pred >
    bool wait_for( std::unique_lock< mutex > & lt,
                   std::chrono::duration< Rep, Period > const& timeout_duration, Pred pred) {
        // pre-condition
        BOOST_ASSERT( lt.owns_lock() );
        BOOST_ASSERT( context::active() == lt.mutex()->owner_);
        bool result = cnd_.wait_for( lt, timeout_duration, pred);
        // post-condition
        BOOST_ASSERT( lt.owns_lock() );
        BOOST_ASSERT( context::active() == lt.mutex()->owner_);
        return result;
    }
};

}}

#ifdef _MSC_VER
# pragma warning(pop)
#endif

#ifdef BOOST_HAS_ABI_HEADERS
#  include BOOST_ABI_SUFFIX
#endif

#endif // BOOST_FIBERS_CONDITION_VARIABLE_H


text:
package backup

import (
	"bytes"
	"crypto/rand"
	"fmt"
	"io"
	"testing"
	"time"

	"github.com/stretchr/testify/require"
	"github.com/zeebo/bencode"
	"github.com/zero-os/0-Disk"
	"github.com/zero-os/0-Disk/errors"
)

func TestHeaderEncoding(t *testing.T) {
	const (
		hashCount = 4096
	)

	require := require.New(t)

	header := &Header{
		Metadata: Metadata{
			SnapshotID: "foo_backup",
			BlockSize:  4096,
			Created:    time.Now().Format(time.RFC3339),
			Source: Source{
				VdiskID:   "foo",
				BlockSize: 4096,
				Size:      16384,
			},
		},
		DedupedMap: RawDedupedMap{
			Count: hashCount,
		},
	}

	// create and set all hashes
	for i := int64(0); i < hashCount; i++ {
		hash := zerodisk.NewHash()
		_, err := rand.Read(hash[:])
		require.NoError(err)

		header.DedupedMap.Hashes = append(
			header.DedupedMap.Hashes, hash)
		header.DedupedMap.Indices = append(
			header.DedupedMap.Indices, i)
	}

	// encode
	buf := bytes.NewBuffer(nil)
	err := encodeHeader(header, buf)
	require.NoError(err)

	t.Logf(
		"header with %d hashes (%d bytes) is encoded into %d bytes",
		hashCount, ((zerodisk.HashSize + 4) * hashCount), len(buf.Bytes()))

	// decode
	outHeader, err := decodeHeader(buf)
	require.NoError(err)
	require.Equal(header.DedupedMap.Count, outHeader.DedupedMap.Count)

	for i := int64(0); i < hashCount; i++ {
		require.Equal(i, header.DedupedMap.Indices[i])
		require.Equal(i, outHeader.DedupedMap.Indices[i])
		require.Equal(header.DedupedMap.Hashes[i], outHeader.DedupedMap.Hashes[i])
	}
}

func TestStoreLoadHeader(t *testing.T) {
	const (
		hashCount  = 4096
		snapshotID = "foo_backup"
	)

	require := require.New(t)

	header := &Header{
		Metadata: Metadata{
			SnapshotID: snapshotID,
			BlockSize:  4096,
			Created:    time.Now().Format(time.RFC3339),
			Source: Source{
				VdiskID:   "foo",
				BlockSize: 4096,
				Size:      16384,
			},
		},
		DedupedMap: RawDedupedMap{
			Count: hashCount,
		},
	}

	// create and set all hashes
	var err error
	for i := int64(0); i < hashCount; i++ {
		hash := zerodisk.NewHash()
		_, err = rand.Read(hash[:])
		require.NoError(err)

		header.DedupedMap.Hashes = append(
			header.DedupedMap.Hashes, hash)
		header.DedupedMap.Indices = append(
			header.DedupedMap.Indices, i)
	}

	// store header

	driver := newStubDriver()
	err = StoreHeader(header, &privKey, LZ4Compression, driver)
	require.NoError(err)

	// load header

	outHeader, err := LoadHeader(snapshotID, driver, &privKey, LZ4Compression)
	require.NoError(err)
	require.Equal(header.DedupedMap.Count, outHeader.DedupedMap.Count)

	// verify loaded header

	for i := int64(0); i < hashCount; i++ {
		require.Equal(i, header.DedupedMap.Indices[i])
		require.Equal(i, outHeader.DedupedMap.Indices[i])
		require.Equal(header.DedupedMap.Hashes[i], outHeader.DedupedMap.Hashes[i])
	}
}

func TestLoadHeader_DeprecatedDedupedMap(t *testing.T) {
	const (
		hashCount  = 128
		snapshotID = "foo_backup"
	)

	require := require.New(t)

	header := &Header{
		Metadata: Metadata{
			SnapshotID: snapshotID,
			BlockSize:  4096,
			Created:    time.Now().Format(time.RFC3339),
			Source: Source{
				VdiskID:   "foo",
				BlockSize: 4096,
				Size:      16384,
			},
		},
	}

	// create fake snapshot blocks (and generate a deduped map that way)

	driver := newStubDriver()
	dm := newDedupedMap()

	// NOTE: that we also need to store the deduped blocks
	pipeline := testExportPipeline(t, driver, dm)
	// as this one is read to get the block size in a slightly hacky way
	for index := int64(0); index < hashCount; index++ {
		err := pipeline.WriteBlock(index, []byte{1, 2, 3, 4, 5, 6, 7, 8})
		require.NoError(err)
	}

	rawDedupedMap, err := dm.Raw()
	require.NoError(err)
	header.DedupedMap = *rawDedupedMap

	// also store the deduped map

	buf := bytes.NewBuffer(nil)
	err = dm.serialize(&privKey, LZ4Compression, buf)
	require.NoError(err)

	err = driver.SetHeader(snapshotID, buf)
	require.NoError(err)

	// load header (this will in fact load the deduped map, with backwards compatibility)

	outHeader, err := LoadHeader(snapshotID, driver, &privKey, LZ4Compression)
	require.NoError(err)

	// verify loaded header

	require.Equal(header.DedupedMap.Count, outHeader.DedupedMap.Count)
	require.Subset(header.DedupedMap.Indices, outHeader.DedupedMap.Indices)
	require.Subset(header.DedupedMap.Hashes, outHeader.DedupedMap.Hashes)
}

func testExportPipeline(t *testing.T, driver StorageDriver, dm *dedupedMap) *exportPipeline {
	require := require.New(t)

	compressor, err := NewCompressor(LZ4Compression)
	require.NoError(err)

	var encrypter Encrypter
	if privKey.Defined() {
		encrypter, err = NewEncrypter(&privKey)
		require.NoError(err)
	}

	hasher, err := newKeyedHasher(LZ4Compression, privKey)
	require.NoError(err)

	return &exportPipeline{
		Hasher:        hasher,
		Compressor:    compressor,
		Encrypter:     encrypter,
		StorageDriver: driver,
		DedupedMap:    dm,
	}
}

// ====
// CODE COPIED FROM REMOVED (OLD) CODE!!
// IT IS ONLY HERE TO EMULATE A SERIALIZED AND DIRECTLY STORED DEDUPED MAP!!
// ====

// serialize allows you to write all data of this map in a binary encoded manner,
// to the given writer. The encoded data will be compressed and encrypted before being
// writen to the given writer.
// You can re-load this map in memory using the `DeserializeDedupedMap` function.
func (dm *dedupedMap) serialize(key *CryptoKey, ct CompressionType, dst io.Writer) error {
	dm.mux.Lock()
	defer dm.mux.Unlock()

	compressor, err := NewCompressor(ct)
	if err != nil {
		return err
	}

	hmbuffer := bytes.NewBuffer(nil)
	err = serializeHashes(dm.hashes, hmbuffer)
	if err != nil {
		return fmt.Errorf("couldn't bencode dedupd map: %v", err)
	}

	if key.Defined() {
		// compress and encrypt
		imbuffer := bytes.NewBuffer(nil)
		err = compressor.Compress(hmbuffer, imbuffer)
		if err != nil {
			return fmt.Errorf("couldn't compress bencoded dedupd map: %v", err)
		}

		err = Encrypt(key, imbuffer, dst)
		if err != nil {
			return fmt.Errorf("couldn't encrypt compressed dedupd map: %v", err)
		}
	} else {
		// only compress
		err = compressor.Compress(hmbuffer, dst)
		if err != nil {
			return fmt.Errorf("couldn't compress bencoded dedupd map: %v", err)
		}
	}

	return nil
}

// serializeHashes encapsulates the entire encoding logic
// for the deduped map serialization.
func serializeHashes(hashes map[int64]zerodisk.Hash, w io.Writer) error {
	hashCount := len(hashes)
	if hashCount == 0 {
		return errors.New("deduped map is empty")
	}

	var format dedupedMapEncodeFormat
	format.Count = int64(hashCount)

	format.Indices = make([]int64, hashCount)
	format.Hashes = make([][]byte, hashCount)

	var i int
	for index, hash := range hashes {
		format.Indices[i] = index
		format.Hashes[i] = hash.Bytes()
		i++
	}

	return bencode.NewEncoder(w).Encode(format)
}

// dedupedMapEncodeFormat defines the structure used to
// encode a deduped map to a binary format.
// See https://github.com/zeebo/bencode for more information.
type dedupedMapEncodeFormat struct {
	Count   int64    `bencode:"c"`
	Indices []int64  `bencode:"i"`
	Hashes  [][]byte `bencode:"h"`
}


text:
//
//  GDataEntryPhotoComment.m
//

#import "GDataEntryPhotoComment.h"
#import "GDataPhotoElements.h"

// extensions

@implementation GDataEntryPhotoComment

+ (GDataEntryPhotoComment *)commentEntryWithString:(NSString *)commentStr {

  GDataEntryPhotoComment *entry = [[[GDataEntryPhotoComment alloc] init] autorelease];

  [entry setNamespaces:[GDataEntryPhotoComment photoNamespaces]];

  [entry setContent:[GDataEntryContent contentWithString:commentStr]];

  return entry;
}

#pragma mark -

+ (NSString *)standardEntryKind {
  return kGDataCategoryPhotosComment;
}

+ (void)load {
  [self registerEntryClass];
}

- (void)addExtensionDeclarations {

  [super addExtensionDeclarations];

  // common photo extensions
  Class entryClass = [self class];

  [self addExtensionDeclarationForParentClass:entryClass
                                 childClasses:
   [GDataPhotoAlbumID class],
   [GDataPhotoPhotoID class],
   nil];
}

#if !GDATA_SIMPLE_DESCRIPTIONS
- (NSMutableArray *)itemsForDescription {

  NSMutableArray *items = [super itemsForDescription];

  [self addToArray:items objectDescriptionIfNonNil:[self albumID] withName:@"albumID"];
  [self addToArray:items objectDescriptionIfNonNil:[self photoID] withName:@"photoID"];

  return items;
}
#endif

#pragma mark -

- (NSString *)albumID {
  GDataPhotoAlbumID *obj = [self objectForExtensionClass:[GDataPhotoAlbumID class]];
  return [obj stringValue];
}

- (void)setAlbumID:(NSString *)str {
  GDataObject *obj = [GDataPhotoAlbumID valueWithString:str];
  [self setObject:obj forExtensionClass:[obj class]];
}

- (NSString *)photoID {
  GDataPhotoPhotoID *obj = [self objectForExtensionClass:[GDataPhotoPhotoID class]];
  return [obj stringValue];
}

- (void)setPhotoID:(NSString *)str {
  GDataObject *obj = [GDataPhotoPhotoID valueWithString:str];
  [self setObject:obj forExtensionClass:[obj class]];
}

@end


text:
Signup for a free 7 day trial

                <form method="post" action="" class="forms">

                        Name
                    *
                    <input type="text" name="user-email" />

                        Email
                    *
                    <input type="email" name="user-email" />

                        Password
                    *
                    <input type="password" name="user-email" />

                    Sign Up

                </form>

These benefits

Title here

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nobis odio sit bahs.

Title here

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nobis odio sit bahs.

Title here

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nobis odio sit bahs.


text:
namespace {

const FX_DWORD kBlockSize = 1024;

}  // namespace

// static
int CPDF_Object::s_nCurRefDepth = 0;

void CPDF_Object::Release() {
  if (m_ObjNum) {
    return;
  }
  Destroy();
}
void CPDF_Object::Destroy() {
  switch (m_Type) {
    case PDFOBJ_STRING:
      delete AsString();
      break;
    case PDFOBJ_NAME:
      delete AsName();
      break;
    case PDFOBJ_ARRAY:
      delete AsArray();
      break;
    case PDFOBJ_DICTIONARY:
      delete AsDictionary();
      break;
    case PDFOBJ_STREAM:
      delete AsStream();
      break;
    default:
      delete this;
  }
}
CFX_ByteString CPDF_Object::GetString() const {
  switch (m_Type) {
    case PDFOBJ_BOOLEAN:
      return AsBoolean()->m_bValue ? "true" : "false";
    case PDFOBJ_NUMBER:
      return AsNumber()->GetString();
    case PDFOBJ_STRING:
      return AsString()->m_String;
    case PDFOBJ_NAME:
      return AsName()->m_Name;
    case PDFOBJ_REFERENCE: {
      const CPDF_Reference* pRef = AsReference();
      if (!pRef->m_pObjList)
        break;

      CPDF_Object* pObj =
          pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum(), nullptr);
      return pObj ? pObj->GetString() : CFX_ByteString();
    }
  }
  return CFX_ByteString();
}
CFX_ByteStringC CPDF_Object::GetConstString() const {
  switch (m_Type) {
    case PDFOBJ_STRING: {
      CFX_ByteString str = AsString()->m_String;
      return CFX_ByteStringC((const uint8_t*)str, str.GetLength());
    }
    case PDFOBJ_NAME: {
      CFX_ByteString name = AsName()->m_Name;
      return CFX_ByteStringC((const uint8_t*)name, name.GetLength());
    }
    case PDFOBJ_REFERENCE: {
      const CPDF_Reference* pRef = AsReference();
      if (!pRef->m_pObjList)
        break;

      CPDF_Object* pObj =
          pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum(), nullptr);
      return pObj ? pObj->GetConstString() : CFX_ByteStringC();
    }
  }
  return CFX_ByteStringC();
}

FX_FLOAT CPDF_Object::GetNumber() const {
  switch (m_Type) {
    case PDFOBJ_NUMBER:
      return AsNumber()->GetNumber();
    case PDFOBJ_REFERENCE: {
      const CPDF_Reference* pRef = AsReference();
      if (!pRef->m_pObjList)
        break;

      CPDF_Object* pObj =
          pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum(), nullptr);
      return pObj ? pObj->GetNumber() : 0;
    }
  }
  return 0;
}

FX_FLOAT CPDF_Object::GetNumber16() const {
  return GetNumber();
}

int CPDF_Object::GetInteger() const {
  CFX_AutoRestorer<int> restorer(&s_nCurRefDepth);
  if (++s_nCurRefDepth > kObjectRefMaxDepth)
    return 0;

  switch (m_Type) {
    case PDFOBJ_BOOLEAN:
      return AsBoolean()->m_bValue;
    case PDFOBJ_NUMBER:
      return AsNumber()->GetInteger();
    case PDFOBJ_REFERENCE: {
      const CPDF_Reference* pRef = AsReference();
      PARSE_CONTEXT context;
      FXSYS_memset(&context, 0, sizeof(PARSE_CONTEXT));
      if (!pRef->m_pObjList)
        return 0;

      CPDF_Object* pObj =
          pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum(), &context);
      return pObj ? pObj->GetInteger() : 0;
    }
  }
  return 0;
}

CPDF_Dictionary* CPDF_Object::GetDict() const {
  switch (m_Type) {
    case PDFOBJ_DICTIONARY:
      // The method should be made non-const if we want to not be const.
      // See bug #234.
      return const_cast<CPDF_Dictionary*>(AsDictionary());
    case PDFOBJ_STREAM:
      return AsStream()->GetDict();
    case PDFOBJ_REFERENCE: {
      const CPDF_Reference* pRef = AsReference();
      CPDF_IndirectObjectHolder* pIndirect = pRef->GetObjList();
      if (!pIndirect)
        return nullptr;
      CPDF_Object* pObj =
          pIndirect->GetIndirectObject(pRef->GetRefObjNum(), nullptr);
      if (!pObj || (pObj == this))
        return nullptr;
      return pObj->GetDict();
    }
    default:
      return nullptr;
  }
}

CPDF_Array* CPDF_Object::GetArray() const {
  // The method should be made non-const if we want to not be const.
  // See bug #234.
  return const_cast<CPDF_Array*>(AsArray());
}

void CPDF_Object::SetString(const CFX_ByteString& str) {
  switch (m_Type) {
    case PDFOBJ_BOOLEAN:
      AsBoolean()->m_bValue = (str == "true");
      return;
    case PDFOBJ_NUMBER:
      AsNumber()->SetString(str);
      return;
    case PDFOBJ_STRING:
      AsString()->m_String = str;
      return;
    case PDFOBJ_NAME:
      AsName()->m_Name = str;
      return;
  }
  ASSERT(FALSE);
}
int CPDF_Object::GetDirectType() const {
  const CPDF_Reference* pRef = AsReference();
  if (!pRef)
    return m_Type;
  return pRef->m_pObjList->GetIndirectType(pRef->GetRefObjNum());
}
FX_BOOL CPDF_Object::IsIdentical(CPDF_Object* pOther) const {
  if (this == pOther)
    return TRUE;
  if (!pOther)
    return FALSE;
  if (pOther->m_Type != m_Type) {
    if (IsReference() && GetDirect())
      return GetDirect()->IsIdentical(pOther);
    if (pOther->IsReference())
      return IsIdentical(pOther->GetDirect());
    return FALSE;
  }
  switch (m_Type) {
    case PDFOBJ_BOOLEAN:
      return AsBoolean()->Identical(pOther->AsBoolean());
    case PDFOBJ_NUMBER:
      return AsNumber()->Identical(pOther->AsNumber());
    case PDFOBJ_STRING:
      return AsString()->Identical(pOther->AsString());
    case PDFOBJ_NAME:
      return AsName()->Identical(pOther->AsName());
    case PDFOBJ_ARRAY:
      return AsArray()->Identical(pOther->AsArray());
    case PDFOBJ_DICTIONARY:
      return AsDictionary()->Identical(pOther->AsDictionary());
    case PDFOBJ_NULL:
      return TRUE;
    case PDFOBJ_STREAM:
      return AsStream()->Identical(pOther->AsStream());
    case PDFOBJ_REFERENCE:
      return AsReference()->Identical(pOther->AsReference());
  }
  return FALSE;
}

CPDF_Object* CPDF_Object::GetDirect() const {
  const CPDF_Reference* pRef = AsReference();
  if (!pRef)
    return const_cast<CPDF_Object*>(this);
  if (!pRef->m_pObjList)
    return nullptr;
  return pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum(), nullptr);
}

CPDF_Object* CPDF_Object::Clone(FX_BOOL bDirect) const {
  std::set<FX_DWORD> visited;
  return CloneInternal(bDirect, &visited);
}
CPDF_Object* CPDF_Object::CloneInternal(FX_BOOL bDirect,
                                        std::set<FX_DWORD>* visited) const {
  switch (m_Type) {
    case PDFOBJ_BOOLEAN:
      return new CPDF_Boolean(AsBoolean()->m_bValue);
    case PDFOBJ_NUMBER: {
      const CPDF_Number* pThis = AsNumber();
      return new CPDF_Number(pThis->m_bInteger ? pThis->m_Integer
                                               : pThis->m_Float);
    }
    case PDFOBJ_STRING: {
      const CPDF_String* pString = AsString();
      return new CPDF_String(pString->m_String, pString->IsHex());
    }
    case PDFOBJ_NAME:
      return new CPDF_Name(AsName()->m_Name);
    case PDFOBJ_ARRAY: {
      CPDF_Array* pCopy = new CPDF_Array();
      const CPDF_Array* pThis = AsArray();
      int n = pThis->GetCount();
      for (int i = 0; i < n; i++) {
        CPDF_Object* value = pThis->m_Objects.GetAt(i);
        pCopy->m_Objects.Add(value->CloneInternal(bDirect, visited));
      }
      return pCopy;
    }
    case PDFOBJ_DICTIONARY: {
      CPDF_Dictionary* pCopy = new CPDF_Dictionary();
      const CPDF_Dictionary* pThis = AsDictionary();
      for (const auto& it : *pThis) {
        pCopy->m_Map.insert(std::make_pair(
            it.first, it.second->CloneInternal(bDirect, visited)));
      }
      return pCopy;
    }
    case PDFOBJ_NULL: {
      return new CPDF_Null;
    }
    case PDFOBJ_STREAM: {
      const CPDF_Stream* pThis = AsStream();
      CPDF_StreamAcc acc;
      acc.LoadAllData(pThis, TRUE);
      FX_DWORD streamSize = acc.GetSize();
      CPDF_Dictionary* pDict = pThis->GetDict();
      if (pDict) {
        pDict = ToDictionary(pDict->CloneInternal(bDirect, visited));
      }
      return new CPDF_Stream(acc.DetachData(), streamSize, pDict);
    }
    case PDFOBJ_REFERENCE: {
      const CPDF_Reference* pRef = AsReference();
      FX_DWORD obj_num = pRef->GetRefObjNum();
      if (bDirect && !pdfium::ContainsKey(*visited, obj_num)) {
        visited->insert(obj_num);
        auto* pDirect = pRef->GetDirect();
        return pDirect ? pDirect->CloneInternal(TRUE, visited) : nullptr;
      }
      return new CPDF_Reference(pRef->m_pObjList, obj_num);
    }
  }
  return NULL;
}
CPDF_Object* CPDF_Object::CloneRef(CPDF_IndirectObjectHolder* pDoc) const {
  if (m_ObjNum) {
    return new CPDF_Reference(pDoc, m_ObjNum);
  }
  return Clone();
}
CFX_WideString CPDF_Object::GetUnicodeText(CFX_CharMap* pCharMap) const {
  if (const CPDF_String* pString = AsString())
    return PDF_DecodeText(pString->m_String, pCharMap);

  if (const CPDF_Stream* pStream = AsStream()) {
    CPDF_StreamAcc stream;
    stream.LoadAllData(pStream, FALSE);
    CFX_WideString result =
        PDF_DecodeText(stream.GetData(), stream.GetSize(), pCharMap);
    return result;
  }
  if (const CPDF_Name* pName = AsName())
    return PDF_DecodeText(pName->m_Name, pCharMap);
  return CFX_WideString();
}
void CPDF_Object::SetUnicodeText(const FX_WCHAR* pUnicodes, int len) {
  if (CPDF_String* pString = AsString()) {
    pString->m_String = PDF_EncodeText(pUnicodes, len);
  } else if (CPDF_Stream* pStream = AsStream()) {
    CFX_ByteString result = PDF_EncodeText(pUnicodes, len);
    pStream->SetData((uint8_t*)result.c_str(), result.GetLength(), FALSE,
                     FALSE);
  }
}

CPDF_Array* CPDF_Object::AsArray() {
  return IsArray() ? static_cast<CPDF_Array*>(this) : nullptr;
}

const CPDF_Array* CPDF_Object::AsArray() const {
  return IsArray() ? static_cast<const CPDF_Array*>(this) : nullptr;
}

CPDF_Boolean* CPDF_Object::AsBoolean() {
  return IsBoolean() ? static_cast<CPDF_Boolean*>(this) : nullptr;
}

const CPDF_Boolean* CPDF_Object::AsBoolean() const {
  return IsBoolean() ? static_cast<const CPDF_Boolean*>(this) : nullptr;
}

CPDF_Dictionary* CPDF_Object::AsDictionary() {
  return IsDictionary() ? static_cast<CPDF_Dictionary*>(this) : nullptr;
}

const CPDF_Dictionary* CPDF_Object::AsDictionary() const {
  return IsDictionary() ? static_cast<const CPDF_Dictionary*>(this) : nullptr;
}

CPDF_Name* CPDF_Object::AsName() {
  return IsName() ? static_cast<CPDF_Name*>(this) : nullptr;
}

const CPDF_Name* CPDF_Object::AsName() const {
  return IsName() ? static_cast<const CPDF_Name*>(this) : nullptr;
}

CPDF_Number* CPDF_Object::AsNumber() {
  return IsNumber() ? static_cast<CPDF_Number*>(this) : nullptr;
}

const CPDF_Number* CPDF_Object::AsNumber() const {
  return IsNumber() ? static_cast<const CPDF_Number*>(this) : nullptr;
}

CPDF_Reference* CPDF_Object::AsReference() {
  return IsReference() ? static_cast<CPDF_Reference*>(this) : nullptr;
}

const CPDF_Reference* CPDF_Object::AsReference() const {
  return IsReference() ? static_cast<const CPDF_Reference*>(this) : nullptr;
}

CPDF_Stream* CPDF_Object::AsStream() {
  return IsStream() ? static_cast<CPDF_Stream*>(this) : nullptr;
}

const CPDF_Stream* CPDF_Object::AsStream() const {
  return IsStream() ? static_cast<const CPDF_Stream*>(this) : nullptr;
}

CPDF_String* CPDF_Object::AsString() {
  return IsString() ? static_cast<CPDF_String*>(this) : nullptr;
}

const CPDF_String* CPDF_Object::AsString() const {
  return IsString() ? static_cast<const CPDF_String*>(this) : nullptr;
}

CPDF_Number::CPDF_Number(int value)
    : CPDF_Object(PDFOBJ_NUMBER), m_bInteger(TRUE), m_Integer(value) {}

CPDF_Number::CPDF_Number(FX_FLOAT value)
    : CPDF_Object(PDFOBJ_NUMBER), m_bInteger(FALSE), m_Float(value) {}

CPDF_Number::CPDF_Number(const CFX_ByteStringC& str)
    : CPDF_Object(PDFOBJ_NUMBER) {
  FX_atonum(str, m_bInteger, &m_Integer);
}

void CPDF_Number::SetString(const CFX_ByteStringC& str) {
  FX_atonum(str, m_bInteger, &m_Integer);
}
FX_BOOL CPDF_Number::Identical(CPDF_Number* pOther) const {
  return m_bInteger == pOther->m_bInteger && m_Integer == pOther->m_Integer;
}
CFX_ByteString CPDF_Number::GetString() const {
  return m_bInteger ? CFX_ByteString::FormatInteger(m_Integer, FXFORMAT_SIGNED)
                    : CFX_ByteString::FormatFloat(m_Float);
}
void CPDF_Number::SetNumber(FX_FLOAT value) {
  m_bInteger = FALSE;
  m_Float = value;
}
CPDF_String::CPDF_String(const CFX_WideString& str)
    : CPDF_Object(PDFOBJ_STRING), m_bHex(FALSE) {
  m_String = PDF_EncodeText(str);
}
CPDF_Array::~CPDF_Array() {
  int size = m_Objects.GetSize();
  CPDF_Object** pList = m_Objects.GetData();
  for (int i = 0; i < size; i++) {
    if (pList[i])
      pList[i]->Release();
  }
}
CFX_FloatRect CPDF_Array::GetRect() {
  CFX_FloatRect rect;
  if (!IsArray() || m_Objects.GetSize() != 4)
    return rect;

  rect.left = GetNumber(0);
  rect.bottom = GetNumber(1);
  rect.right = GetNumber(2);
  rect.top = GetNumber(3);
  return rect;
}
CFX_Matrix CPDF_Array::GetMatrix() {
  CFX_Matrix matrix;
  if (!IsArray() || m_Objects.GetSize() != 6)
    return matrix;

  matrix.Set(GetNumber(0), GetNumber(1), GetNumber(2), GetNumber(3),
             GetNumber(4), GetNumber(5));
  return matrix;
}
CPDF_Object* CPDF_Array::GetElement(FX_DWORD i) const {
  if (i >= (FX_DWORD)m_Objects.GetSize())
    return nullptr;
  return m_Objects.GetAt(i);
}
CPDF_Object* CPDF_Array::GetElementValue(FX_DWORD i) const {
  if (i >= (FX_DWORD)m_Objects.GetSize())
    return nullptr;
  return m_Objects.GetAt(i)->GetDirect();
}
CFX_ByteString CPDF_Array::GetString(FX_DWORD i) const {
  if (i >= (FX_DWORD)m_Objects.GetSize())
    return CFX_ByteString();
  return m_Objects.GetAt(i)->GetString();
}
CFX_ByteStringC CPDF_Array::GetConstString(FX_DWORD i) const {
  if (i >= (FX_DWORD)m_Objects.GetSize())
    return CFX_ByteStringC();
  return m_Objects.GetAt(i)->GetConstString();
}
int CPDF_Array::GetInteger(FX_DWORD i) const {
  if (i >= (FX_DWORD)m_Objects.GetSize())
    return 0;
  return m_Objects.GetAt(i)->GetInteger();
}
FX_FLOAT CPDF_Array::GetNumber(FX_DWORD i) const {
  if (i >= (FX_DWORD)m_Objects.GetSize())
    return 0;
  return m_Objects.GetAt(i)->GetNumber();
}
CPDF_Dictionary* CPDF_Array::GetDict(FX_DWORD i) const {
  CPDF_Object* p = GetElementValue(i);
  if (!p)
    return NULL;
  if (CPDF_Dictionary* pDict = p->AsDictionary())
    return pDict;
  if (CPDF_Stream* pStream = p->AsStream())
    return pStream->GetDict();
  return NULL;
}
CPDF_Stream* CPDF_Array::GetStream(FX_DWORD i) const {
  return ToStream(GetElementValue(i));
}
CPDF_Array* CPDF_Array::GetArray(FX_DWORD i) const {
  return ToArray(GetElementValue(i));
}
void CPDF_Array::RemoveAt(FX_DWORD i, int nCount) {
  if (i >= (FX_DWORD)m_Objects.GetSize())
    return;

  if (nCount <= 0 || nCount > m_Objects.GetSize() - i)
    return;

  for (int j = 0; j < nCount; ++j) {
    if (CPDF_Object* p = m_Objects.GetAt(i + j))
      p->Release();
  }
  m_Objects.RemoveAt(i, nCount);
}
void CPDF_Array::SetAt(FX_DWORD i,
                       CPDF_Object* pObj,
                       CPDF_IndirectObjectHolder* pObjs) {
  ASSERT(IsArray());
  ASSERT(i < (FX_DWORD)m_Objects.GetSize());
  if (i >= (FX_DWORD)m_Objects.GetSize())
    return;
  if (CPDF_Object* pOld = m_Objects.GetAt(i))
    pOld->Release();
  if (pObj->GetObjNum()) {
    ASSERT(pObjs);
    pObj = new CPDF_Reference(pObjs, pObj->GetObjNum());
  }
  m_Objects.SetAt(i, pObj);
}
void CPDF_Array::InsertAt(FX_DWORD index,
                          CPDF_Object* pObj,
                          CPDF_IndirectObjectHolder* pObjs) {
  if (pObj->GetObjNum()) {
    ASSERT(pObjs);
    pObj = new CPDF_Reference(pObjs, pObj->GetObjNum());
  }
  m_Objects.InsertAt(index, pObj);
}
void CPDF_Array::Add(CPDF_Object* pObj, CPDF_IndirectObjectHolder* pObjs) {
  if (pObj->GetObjNum()) {
    ASSERT(pObjs);
    pObj = new CPDF_Reference(pObjs, pObj->GetObjNum());
  }
  m_Objects.Add(pObj);
}
void CPDF_Array::AddName(const CFX_ByteString& str) {
  ASSERT(IsArray());
  Add(new CPDF_Name(str));
}
void CPDF_Array::AddString(const CFX_ByteString& str) {
  ASSERT(IsArray());
  Add(new CPDF_String(str, FALSE));
}
void CPDF_Array::AddInteger(int i) {
  ASSERT(IsArray());
  Add(new CPDF_Number(i));
}
void CPDF_Array::AddNumber(FX_FLOAT f) {
  ASSERT(IsArray());
  CPDF_Number* pNumber = new CPDF_Number;
  pNumber->SetNumber(f);
  Add(pNumber);
}
void CPDF_Array::AddReference(CPDF_IndirectObjectHolder* pDoc,
                              FX_DWORD objnum) {
  ASSERT(IsArray());
  Add(new CPDF_Reference(pDoc, objnum));
}
FX_BOOL CPDF_Array::Identical(CPDF_Array* pOther) const {
  if (m_Objects.GetSize() != pOther->m_Objects.GetSize()) {
    return FALSE;
  }
  for (int i = 0; i < m_Objects.GetSize(); i++) {
    if (!m_Objects[i]->IsIdentical(pOther->m_Objects[i]))
      return FALSE;
  }
  return TRUE;
}
CPDF_Dictionary::~CPDF_Dictionary() {
  for (const auto& it : m_Map) {
    it.second->Release();
  }
}
CPDF_Object* CPDF_Dictionary::GetElement(const CFX_ByteStringC& key) const {
  auto it = m_Map.find(key);
  if (it == m_Map.end())
    return nullptr;
  return it->second;
}
CPDF_Object* CPDF_Dictionary::GetElementValue(
    const CFX_ByteStringC& key) const {
  CPDF_Object* p = GetElement(key);
  return p ? p->GetDirect() : nullptr;
}
CFX_ByteString CPDF_Dictionary::GetString(const CFX_ByteStringC& key) const {
  CPDF_Object* p = GetElement(key);
  if (p) {
    return p->GetString();
  }
  return CFX_ByteString();
}
CFX_ByteStringC CPDF_Dictionary::GetConstString(
    const CFX_ByteStringC& key) const {
  CPDF_Object* p = GetElement(key);
  if (p) {
    return p->GetConstString();
  }
  return CFX_ByteStringC();
}
CFX_WideString CPDF_Dictionary::GetUnicodeText(const CFX_ByteStringC& key,
                                               CFX_CharMap* pCharMap) const {
  CPDF_Object* p = GetElement(key);
  if (CPDF_Reference* pRef = ToReference(p))
    p = pRef->GetDirect();
  return p ? p->GetUnicodeText(pCharMap) : CFX_WideString();
}
CFX_ByteString CPDF_Dictionary::GetString(const CFX_ByteStringC& key,
                                          const CFX_ByteStringC& def) const {
  CPDF_Object* p = GetElement(key);
  if (p) {
    return p->GetString();
  }
  return CFX_ByteString(def);
}
CFX_ByteStringC CPDF_Dictionary::GetConstString(
    const CFX_ByteStringC& key,
    const CFX_ByteStringC& def) const {
  CPDF_Object* p = GetElement(key);
  if (p) {
    return p->GetConstString();
  }
  return CFX_ByteStringC(def);
}
int CPDF_Dictionary::GetInteger(const CFX_ByteStringC& key) const {
  CPDF_Object* p = GetElement(key);
  if (p) {
    return p->GetInteger();
  }
  return 0;
}
int CPDF_Dictionary::GetInteger(const CFX_ByteStringC& key, int def) const {
  CPDF_Object* p = GetElement(key);
  if (p) {
    return p->GetInteger();
  }
  return def;
}
FX_FLOAT CPDF_Dictionary::GetNumber(const CFX_ByteStringC& key) const {
  CPDF_Object* p = GetElement(key);
  if (p) {
    return p->GetNumber();
  }
  return 0;
}
FX_BOOL CPDF_Dictionary::GetBoolean(const CFX_ByteStringC& key,
                                    FX_BOOL bDefault) const {
  CPDF_Object* p = GetElement(key);
  if (ToBoolean(p))
    return p->GetInteger();
  return bDefault;
}
CPDF_Dictionary* CPDF_Dictionary::GetDict(const CFX_ByteStringC& key) const {
  CPDF_Object* p = GetElementValue(key);
  if (!p)
    return nullptr;
  if (CPDF_Dictionary* pDict = p->AsDictionary())
    return pDict;
  if (CPDF_Stream* pStream = p->AsStream())
    return pStream->GetDict();
  return nullptr;
}
CPDF_Array* CPDF_Dictionary::GetArray(const CFX_ByteStringC& key) const {
  return ToArray(GetElementValue(key));
}
CPDF_Stream* CPDF_Dictionary::GetStream(const CFX_ByteStringC& key) const {
  return ToStream(GetElementValue(key));
}
CFX_FloatRect CPDF_Dictionary::GetRect(const CFX_ByteStringC& key) const {
  CFX_FloatRect rect;
  CPDF_Array* pArray = GetArray(key);
  if (pArray)
    rect = pArray->GetRect();
  return rect;
}
CFX_Matrix CPDF_Dictionary::GetMatrix(const CFX_ByteStringC& key) const {
  CFX_Matrix matrix;
  CPDF_Array* pArray = GetArray(key);
  if (pArray)
    matrix = pArray->GetMatrix();
  return matrix;
}
FX_BOOL CPDF_Dictionary::KeyExist(const CFX_ByteStringC& key) const {
  return pdfium::ContainsKey(m_Map, key);
}

void CPDF_Dictionary::SetAt(const CFX_ByteStringC& key, CPDF_Object* pObj) {
  ASSERT(IsDictionary());
  // Avoid 2 constructions of CFX_ByteString.
  CFX_ByteString key_bytestring = key;
  auto it = m_Map.find(key_bytestring);
  if (it == m_Map.end()) {
    if (pObj) {
      m_Map.insert(std::make_pair(key_bytestring, pObj));
    }
    return;
  }

  if (it->second == pObj)
    return;
  it->second->Release();

  if (pObj)
    it->second = pObj;
  else
    m_Map.erase(it);
}
void CPDF_Dictionary::RemoveAt(const CFX_ByteStringC& key) {
  ASSERT(m_Type == PDFOBJ_DICTIONARY);
  auto it = m_Map.find(key);
  if (it == m_Map.end())
    return;

  it->second->Release();
  m_Map.erase(it);
}
void CPDF_Dictionary::ReplaceKey(const CFX_ByteStringC& oldkey,
                                 const CFX_ByteStringC& newkey) {
  ASSERT(m_Type == PDFOBJ_DICTIONARY);
  auto old_it = m_Map.find(oldkey);
  if (old_it == m_Map.end())
    return;

  // Avoid 2 constructions of CFX_ByteString.
  CFX_ByteString newkey_bytestring = newkey;
  auto new_it = m_Map.find(newkey_bytestring);
  if (new_it == old_it)
    return;

  if (new_it != m_Map.end()) {
    new_it->second->Release();
    new_it->second = old_it->second;
  } else {
    m_Map.insert(std::make_pair(newkey_bytestring, old_it->second));
  }
  m_Map.erase(old_it);
}
FX_BOOL CPDF_Dictionary::Identical(CPDF_Dictionary* pOther) const {
  if (!pOther) {
    return FALSE;
  }
  if (m_Map.size() != pOther->m_Map.size()) {
    return FALSE;
  }
  for (const auto& it : m_Map) {
    const CFX_ByteString& key = it.first;
    if (!it.second->IsIdentical(pOther->GetElement(key)))
      return FALSE;
  }
  return TRUE;
}
void CPDF_Dictionary::SetAtInteger(const CFX_ByteStringC& key, int i) {
  SetAt(key, new CPDF_Number(i));
}
void CPDF_Dictionary::SetAtName(const CFX_ByteStringC& key,
                                const CFX_ByteString& name) {
  SetAt(key, new CPDF_Name(name));
}
void CPDF_Dictionary::SetAtString(const CFX_ByteStringC& key,
                                  const CFX_ByteString& str) {
  SetAt(key, new CPDF_String(str, FALSE));
}
void CPDF_Dictionary::SetAtReference(const CFX_ByteStringC& key,
                                     CPDF_IndirectObjectHolder* pDoc,
                                     FX_DWORD objnum) {
  SetAt(key, new CPDF_Reference(pDoc, objnum));
}
void CPDF_Dictionary::AddReference(const CFX_ByteStringC& key,
                                   CPDF_IndirectObjectHolder* pDoc,
                                   FX_DWORD objnum) {
  SetAt(key, new CPDF_Reference(pDoc, objnum));
}
void CPDF_Dictionary::SetAtNumber(const CFX_ByteStringC& key, FX_FLOAT f) {
  CPDF_Number* pNumber = new CPDF_Number;
  pNumber->SetNumber(f);
  SetAt(key, pNumber);
}
void CPDF_Dictionary::SetAtBoolean(const CFX_ByteStringC& key, FX_BOOL bValue) {
  SetAt(key, new CPDF_Boolean(bValue));
}
void CPDF_Dictionary::SetAtRect(const CFX_ByteStringC& key,
                                const CFX_FloatRect& rect) {
  CPDF_Array* pArray = new CPDF_Array;
  pArray->AddNumber(rect.left);
  pArray->AddNumber(rect.bottom);
  pArray->AddNumber(rect.right);
  pArray->AddNumber(rect.top);
  SetAt(key, pArray);
}
void CPDF_Dictionary::SetAtMatrix(const CFX_ByteStringC& key,
                                  const CFX_Matrix& matrix) {
  CPDF_Array* pArray = new CPDF_Array;
  pArray->AddNumber16(matrix.a);
  pArray->AddNumber16(matrix.b);
  pArray->AddNumber16(matrix.c);
  pArray->AddNumber16(matrix.d);
  pArray->AddNumber(matrix.e);
  pArray->AddNumber(matrix.f);
  SetAt(key, pArray);
}
CPDF_Stream::CPDF_Stream(uint8_t* pData, FX_DWORD size, CPDF_Dictionary* pDict)
    : CPDF_Object(PDFOBJ_STREAM),
      m_pDict(pDict),
      m_dwSize(size),
      m_GenNum(kMemoryBasedGenNum),
      m_pDataBuf(pData) {}

CPDF_Stream::~CPDF_Stream() {
  if (IsMemoryBased())
    FX_Free(m_pDataBuf);

  if (m_pDict)
    m_pDict->Release();
}

void CPDF_Stream::InitStreamInternal(CPDF_Dictionary* pDict) {
  if (pDict) {
    if (m_pDict)
      m_pDict->Release();
    m_pDict = pDict;
  }
  if (IsMemoryBased())
    FX_Free(m_pDataBuf);

  m_GenNum = 0;
  m_pFile = nullptr;
}

void CPDF_Stream::InitStream(uint8_t* pData,
                             FX_DWORD size,
                             CPDF_Dictionary* pDict) {
  InitStreamInternal(pDict);
  m_GenNum = kMemoryBasedGenNum;
  m_pDataBuf = FX_Alloc(uint8_t, size);
  if (pData) {
    FXSYS_memcpy(m_pDataBuf, pData, size);
  }
  m_dwSize = size;
  if (m_pDict) {
    m_pDict->SetAtInteger("Length", size);
  }
}
void CPDF_Stream::SetData(const uint8_t* pData,
                          FX_DWORD size,
                          FX_BOOL bCompressed,
                          FX_BOOL bKeepBuf) {
  if (IsMemoryBased())
    FX_Free(m_pDataBuf);
  m_GenNum = kMemoryBasedGenNum;

  if (bKeepBuf) {
    m_pDataBuf = (uint8_t*)pData;
  } else {
    m_pDataBuf = FX_Alloc(uint8_t, size);
    if (pData) {
      FXSYS_memcpy(m_pDataBuf, pData, size);
    }
  }
  m_dwSize = size;
  if (!m_pDict)
    m_pDict = new CPDF_Dictionary;
  m_pDict->SetAtInteger("Length", size);
  if (!bCompressed) {
    m_pDict->RemoveAt("Filter");
    m_pDict->RemoveAt("DecodeParms");
  }
}
FX_BOOL CPDF_Stream::ReadRawData(FX_FILESIZE offset,
                                 uint8_t* buf,
                                 FX_DWORD size) const {
  if (!IsMemoryBased() && m_pFile)
    return m_pFile->ReadBlock(buf, offset, size);

  if (m_pDataBuf)
    FXSYS_memcpy(buf, m_pDataBuf + offset, size);
  return TRUE;
}
void CPDF_Stream::InitStreamFromFile(IFX_FileRead* pFile,
                                     CPDF_Dictionary* pDict) {
  InitStreamInternal(pDict);
  m_pFile = pFile;
  m_dwSize = (FX_DWORD)pFile->GetSize();
  if (m_pDict) {
    m_pDict->SetAtInteger("Length", m_dwSize);
  }
}

FX_BOOL CPDF_Stream::Identical(CPDF_Stream* pOther) const {
  if (!m_pDict)
    return !pOther->m_pDict;

  if (!m_pDict->Identical(pOther->m_pDict))
    return FALSE;

  if (m_dwSize != pOther->m_dwSize)
    return FALSE;

  if (!IsMemoryBased() && !pOther->IsMemoryBased()) {
    if (m_pFile == pOther->m_pFile && !m_pFile)
      return TRUE;

    if (!m_pFile || !pOther->m_pFile)
      return FALSE;

    uint8_t srcBuf[kBlockSize];
    uint8_t destBuf[kBlockSize];
    FX_DWORD size = m_dwSize;
    if (m_pFile == pOther->m_pFile)
      return TRUE;

    FX_DWORD offset = 0;
    while (size > 0) {
      FX_DWORD actualSize = std::min(size, kBlockSize);
      m_pFile->ReadBlock(srcBuf, offset, actualSize);
      pOther->m_pFile->ReadBlock(destBuf, offset, actualSize);
      if (FXSYS_memcmp(srcBuf, destBuf, actualSize) != 0)
        return FALSE;

      size -= actualSize;
      offset += actualSize;
    }
    return TRUE;
  }

  if (!IsMemoryBased() || !pOther->IsMemoryBased()) {
    IFX_FileRead* pFile = nullptr;
    uint8_t* pBuf = nullptr;
    if (!pOther->IsMemoryBased()) {
      pFile = pOther->m_pFile;
      pBuf = m_pDataBuf;
    } else if (!IsMemoryBased()) {
      pFile = m_pFile;
      pBuf = pOther->m_pDataBuf;
    }
    if (!pBuf)
      return FALSE;

    uint8_t srcBuf[kBlockSize];
    FX_DWORD size = m_dwSize;
    FX_DWORD offset = 0;
    while (size > 0) {
      FX_DWORD actualSize = std::min(size, kBlockSize);
      pFile->ReadBlock(srcBuf, offset, actualSize);
      if (FXSYS_memcmp(srcBuf, pBuf, actualSize) != 0)
        return FALSE;

      pBuf += actualSize;
      size -= actualSize;
      offset += actualSize;
    }
    return TRUE;
  }
  return FXSYS_memcmp(m_pDataBuf, pOther->m_pDataBuf, m_dwSize) == 0;
}

CPDF_StreamAcc::CPDF_StreamAcc() {
  m_bNewBuf = FALSE;
  m_pData = NULL;
  m_dwSize = 0;
  m_pImageParam = NULL;
  m_pStream = NULL;
  m_pSrcData = NULL;
}
void CPDF_StreamAcc::LoadAllData(const CPDF_Stream* pStream,
                                 FX_BOOL bRawAccess,
                                 FX_DWORD estimated_size,
                                 FX_BOOL bImageAcc) {
  if (!pStream)
    return;

  m_pStream = pStream;
  if (pStream->IsMemoryBased() &&
      (!pStream->GetDict()->KeyExist("Filter") || bRawAccess)) {
    m_dwSize = pStream->m_dwSize;
    m_pData = (uint8_t*)pStream->m_pDataBuf;
    return;
  }
  uint8_t* pSrcData;
  FX_DWORD dwSrcSize = pStream->m_dwSize;
  if (dwSrcSize == 0)
    return;

  if (!pStream->IsMemoryBased()) {
    pSrcData = m_pSrcData = FX_Alloc(uint8_t, dwSrcSize);
    if (!pStream->ReadRawData(0, pSrcData, dwSrcSize))
      return;
  } else {
    pSrcData = pStream->m_pDataBuf;
  }
  uint8_t* pDecryptedData = pSrcData;
  FX_DWORD dwDecryptedSize = dwSrcSize;
  if (!pStream->GetDict()->KeyExist("Filter") || bRawAccess) {
    m_pData = pDecryptedData;
    m_dwSize = dwDecryptedSize;
  } else {
    FX_BOOL bRet = PDF_DataDecode(
        pDecryptedData, dwDecryptedSize, m_pStream->GetDict(), m_pData,
        m_dwSize, m_ImageDecoder, m_pImageParam, estimated_size, bImageAcc);
    if (!bRet) {
      m_pData = pDecryptedData;
      m_dwSize = dwDecryptedSize;
    }
  }
  if (pSrcData != pStream->m_pDataBuf && pSrcData != m_pData) {
    FX_Free(pSrcData);
  }
  if (pDecryptedData != pSrcData && pDecryptedData != m_pData) {
    FX_Free(pDecryptedData);
  }
  m_pSrcData = NULL;
  m_bNewBuf = m_pData != pStream->m_pDataBuf;
}
CPDF_StreamAcc::~CPDF_StreamAcc() {
  if (m_bNewBuf) {
    FX_Free(m_pData);
  }
  FX_Free(m_pSrcData);
}
const uint8_t* CPDF_StreamAcc::GetData() const {
  if (m_bNewBuf) {
    return m_pData;
  }
  if (!m_pStream) {
    return NULL;
  }
  return m_pStream->m_pDataBuf;
}
FX_DWORD CPDF_StreamAcc::GetSize() const {
  if (m_bNewBuf) {
    return m_dwSize;
  }
  if (!m_pStream) {
    return 0;
  }
  return m_pStream->m_dwSize;
}
uint8_t* CPDF_StreamAcc::DetachData() {
  if (m_bNewBuf) {
    uint8_t* p = m_pData;
    m_pData = NULL;
    m_dwSize = 0;
    return p;
  }
  uint8_t* p = FX_Alloc(uint8_t, m_dwSize);
  FXSYS_memcpy(p, m_pData, m_dwSize);
  return p;
}
void CPDF_Reference::SetRef(CPDF_IndirectObjectHolder* pDoc, FX_DWORD objnum) {
  m_pObjList = pDoc;
  m_RefObjNum = objnum;
}
CPDF_IndirectObjectHolder::CPDF_IndirectObjectHolder(CPDF_Parser* pParser)
    : m_pParser(pParser), m_LastObjNum(0) {
  if (pParser)
    m_LastObjNum = m_pParser->GetLastObjNum();
}
CPDF_IndirectObjectHolder::~CPDF_IndirectObjectHolder() {
  for (const auto& pair : m_IndirectObjs) {
    pair.second->Destroy();
  }
}
CPDF_Object* CPDF_IndirectObjectHolder::GetIndirectObject(
    FX_DWORD objnum,
    PARSE_CONTEXT* pContext) {
  if (objnum == 0)
    return nullptr;

  auto it = m_IndirectObjs.find(objnum);
  if (it != m_IndirectObjs.end())
    return it->second->GetObjNum() != -1 ? it->second : nullptr;

  if (!m_pParser)
    return nullptr;

  CPDF_Object* pObj = m_pParser->ParseIndirectObject(this, objnum, pContext);
  if (!pObj)
    return nullptr;

  pObj->m_ObjNum = objnum;
  m_LastObjNum = std::max(m_LastObjNum, objnum);
  if (m_IndirectObjs[objnum])
    m_IndirectObjs[objnum]->Destroy();

  m_IndirectObjs[objnum] = pObj;
  return pObj;
}
int CPDF_IndirectObjectHolder::GetIndirectType(FX_DWORD objnum) {
  auto it = m_IndirectObjs.find(objnum);
  if (it != m_IndirectObjs.end())
    return it->second->GetType();

  if (!m_pParser)
    return 0;

  PARSE_CONTEXT context;
  FXSYS_memset(&context, 0, sizeof(PARSE_CONTEXT));
  context.m_Flags = PDFPARSE_TYPEONLY;
  return (int)(uintptr_t)m_pParser->ParseIndirectObject(this, objnum, &context);
}
FX_DWORD CPDF_IndirectObjectHolder::AddIndirectObject(CPDF_Object* pObj) {
  if (pObj->m_ObjNum) {
    return pObj->m_ObjNum;
  }
  m_LastObjNum++;
  m_IndirectObjs[m_LastObjNum] = pObj;
  pObj->m_ObjNum = m_LastObjNum;
  return m_LastObjNum;
}
void CPDF_IndirectObjectHolder::ReleaseIndirectObject(FX_DWORD objnum) {
  auto it = m_IndirectObjs.find(objnum);
  if (it == m_IndirectObjs.end() || it->second->GetObjNum() == -1)
    return;
  it->second->Destroy();
  m_IndirectObjs.erase(it);
}
FX_BOOL CPDF_IndirectObjectHolder::InsertIndirectObject(FX_DWORD objnum,
                                                        CPDF_Object* pObj) {
  if (!objnum || !pObj)
    return FALSE;
  auto it = m_IndirectObjs.find(objnum);
  if (it != m_IndirectObjs.end()) {
    if (pObj->GetGenNum() <= it->second->GetGenNum()) {
      pObj->Destroy();
      return FALSE;
    }
    it->second->Destroy();
  }
  pObj->m_ObjNum = objnum;
  m_IndirectObjs[objnum] = pObj;
  m_LastObjNum = std::max(m_LastObjNum, objnum);
  return TRUE;
}