first commit

master
jokingww 4 years ago
parent c27cccda87
commit d65fdcc0df

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/../../../../../../../:\Study\2021春\人工智能\SearchFramework1.0.2\SearchFramework1.0.1\.idea/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/SearchFramework1.0.1.iml" filepath="$PROJECT_DIR$/SearchFramework1.0.1.iml" />
</modules>
</component>
</project>

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library" exported="">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/../../algs4.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$MODULE_DIR$/../../algs4.jar!/" />
</SOURCES>
</library>
</orderEntry>
<orderEntry type="module-library" exported="">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/../../junit-jupiter-api-5.4.2.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: runner.SearchRunner

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CheckStyle-IDEA">
<option name="configuration">
<map>
<entry key="checkstyle-version" value="8.40" />
<entry key="copy-libs" value="true" />
<entry key="location-0" value="BUNDLED:(bundled):Sun Checks" />
<entry key="location-1" value="BUNDLED:(bundled):Google Checks" />
<entry key="scan-before-checkin" value="false" />
<entry key="scanscope" value="JavaOnly" />
<entry key="suppress-errors" value="false" />
</map>
</option>
</component>
</project>

@ -0,0 +1,464 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DBNavigator.Project.DataEditorManager">
<record-view-column-sorting-type value="BY_INDEX" />
<value-preview-text-wrapping value="true" />
<value-preview-pinned value="false" />
</component>
<component name="DBNavigator.Project.DataExportManager">
<export-instructions>
<create-header value="true" />
<friendly-headers value="false" />
<quote-values-containing-separator value="true" />
<quote-all-values value="false" />
<value-separator value="" />
<file-name value="" />
<file-location value="" />
<scope value="GLOBAL" />
<destination value="FILE" />
<format value="EXCEL" />
<charset value="GBK" />
</export-instructions>
</component>
<component name="DBNavigator.Project.DatabaseBrowserManager">
<autoscroll-to-editor value="false" />
<autoscroll-from-editor value="true" />
<show-object-properties value="true" />
<loaded-nodes />
</component>
<component name="DBNavigator.Project.DatabaseFileManager">
<open-files />
</component>
<component name="DBNavigator.Project.EditorStateManager">
<last-used-providers />
</component>
<component name="DBNavigator.Project.ExecutionManager">
<retain-sticky-names value="false" />
</component>
<component name="DBNavigator.Project.MethodExecutionManager">
<method-browser />
<execution-history>
<group-entries value="true" />
<execution-inputs />
</execution-history>
<argument-values-cache />
</component>
<component name="DBNavigator.Project.ObjectDependencyManager">
<last-used-dependency-type value="INCOMING" />
</component>
<component name="DBNavigator.Project.ObjectQuickFilterManager">
<last-used-operator value="EQUAL" />
<filters />
</component>
<component name="DBNavigator.Project.ScriptExecutionManager" clear-outputs="true">
<recently-used-interfaces />
</component>
<component name="DBNavigator.Project.Settings">
<connections />
<browser-settings>
<general>
<display-mode value="TABBED" />
<navigation-history-size value="100" />
<show-object-details value="false" />
</general>
<filters>
<object-type-filter>
<object-type name="SCHEMA" enabled="true" />
<object-type name="USER" enabled="true" />
<object-type name="ROLE" enabled="true" />
<object-type name="PRIVILEGE" enabled="true" />
<object-type name="CHARSET" enabled="true" />
<object-type name="TABLE" enabled="true" />
<object-type name="VIEW" enabled="true" />
<object-type name="MATERIALIZED_VIEW" enabled="true" />
<object-type name="NESTED_TABLE" enabled="true" />
<object-type name="COLUMN" enabled="true" />
<object-type name="INDEX" enabled="true" />
<object-type name="CONSTRAINT" enabled="true" />
<object-type name="DATASET_TRIGGER" enabled="true" />
<object-type name="DATABASE_TRIGGER" enabled="true" />
<object-type name="SYNONYM" enabled="true" />
<object-type name="SEQUENCE" enabled="true" />
<object-type name="PROCEDURE" enabled="true" />
<object-type name="FUNCTION" enabled="true" />
<object-type name="PACKAGE" enabled="true" />
<object-type name="TYPE" enabled="true" />
<object-type name="TYPE_ATTRIBUTE" enabled="true" />
<object-type name="ARGUMENT" enabled="true" />
<object-type name="DIMENSION" enabled="true" />
<object-type name="CLUSTER" enabled="true" />
<object-type name="DBLINK" enabled="true" />
</object-type-filter>
</filters>
<sorting>
<object-type name="COLUMN" sorting-type="NAME" />
<object-type name="FUNCTION" sorting-type="NAME" />
<object-type name="PROCEDURE" sorting-type="NAME" />
<object-type name="ARGUMENT" sorting-type="POSITION" />
</sorting>
<default-editors>
<object-type name="VIEW" editor-type="SELECTION" />
<object-type name="PACKAGE" editor-type="SELECTION" />
<object-type name="TYPE" editor-type="SELECTION" />
</default-editors>
</browser-settings>
<navigation-settings>
<lookup-filters>
<lookup-objects>
<object-type name="SCHEMA" enabled="true" />
<object-type name="USER" enabled="false" />
<object-type name="ROLE" enabled="false" />
<object-type name="PRIVILEGE" enabled="false" />
<object-type name="CHARSET" enabled="false" />
<object-type name="TABLE" enabled="true" />
<object-type name="VIEW" enabled="true" />
<object-type name="MATERIALIZED VIEW" enabled="true" />
<object-type name="INDEX" enabled="true" />
<object-type name="CONSTRAINT" enabled="true" />
<object-type name="DATASET TRIGGER" enabled="true" />
<object-type name="DATABASE TRIGGER" enabled="true" />
<object-type name="SYNONYM" enabled="false" />
<object-type name="SEQUENCE" enabled="true" />
<object-type name="PROCEDURE" enabled="true" />
<object-type name="FUNCTION" enabled="true" />
<object-type name="PACKAGE" enabled="true" />
<object-type name="TYPE" enabled="true" />
<object-type name="DIMENSION" enabled="false" />
<object-type name="CLUSTER" enabled="false" />
<object-type name="DBLINK" enabled="true" />
</lookup-objects>
<force-database-load value="false" />
<prompt-connection-selection value="true" />
<prompt-schema-selection value="true" />
</lookup-filters>
</navigation-settings>
<dataset-grid-settings>
<general>
<enable-zooming value="true" />
<enable-column-tooltip value="true" />
</general>
<sorting>
<nulls-first value="true" />
<max-sorting-columns value="4" />
</sorting>
<tracking-columns>
<columnNames value="" />
<visible value="true" />
<editable value="false" />
</tracking-columns>
</dataset-grid-settings>
<dataset-editor-settings>
<text-editor-popup>
<active value="false" />
<active-if-empty value="false" />
<data-length-threshold value="100" />
<popup-delay value="1000" />
</text-editor-popup>
<values-actions-popup>
<show-popup-button value="true" />
<element-count-threshold value="1000" />
<data-length-threshold value="250" />
</values-actions-popup>
<general>
<fetch-block-size value="100" />
<fetch-timeout value="30" />
<trim-whitespaces value="true" />
<convert-empty-strings-to-null value="true" />
<select-content-on-cell-edit value="true" />
<large-value-preview-active value="true" />
</general>
<filters>
<prompt-filter-dialog value="true" />
<default-filter-type value="BASIC" />
</filters>
<qualified-text-editor text-length-threshold="300">
<content-types>
<content-type name="Text" enabled="true" />
<content-type name="Properties" enabled="true" />
<content-type name="XML" enabled="true" />
<content-type name="DTD" enabled="true" />
<content-type name="HTML" enabled="true" />
<content-type name="XHTML" enabled="true" />
<content-type name="CSS" enabled="true" />
<content-type name="Java" enabled="true" />
<content-type name="SQL" enabled="true" />
<content-type name="PL/SQL" enabled="true" />
<content-type name="JavaScript" enabled="true" />
<content-type name="JSON" enabled="true" />
<content-type name="JSON5" enabled="true" />
<content-type name="JSP" enabled="true" />
<content-type name="JSPx" enabled="true" />
<content-type name="Groovy" enabled="true" />
<content-type name="FTL" enabled="true" />
<content-type name="GSP" enabled="true" />
<content-type name="VTL" enabled="true" />
<content-type name="YAML" enabled="true" />
<content-type name="Manifest" enabled="true" />
</content-types>
</qualified-text-editor>
<record-navigation>
<navigation-target value="VIEWER" />
</record-navigation>
</dataset-editor-settings>
<code-editor-settings>
<general>
<show-object-navigation-gutter value="false" />
<show-spec-declaration-navigation-gutter value="true" />
<enable-spellchecking value="true" />
<enable-reference-spellchecking value="false" />
</general>
<confirmations>
<save-changes value="false" />
<revert-changes value="true" />
</confirmations>
</code-editor-settings>
<code-completion-settings>
<filters>
<basic-filter>
<filter-element type="RESERVED_WORD" id="keyword" selected="true" />
<filter-element type="RESERVED_WORD" id="function" selected="true" />
<filter-element type="RESERVED_WORD" id="parameter" selected="true" />
<filter-element type="RESERVED_WORD" id="datatype" selected="true" />
<filter-element type="RESERVED_WORD" id="exception" selected="true" />
<filter-element type="OBJECT" id="schema" selected="true" />
<filter-element type="OBJECT" id="role" selected="true" />
<filter-element type="OBJECT" id="user" selected="true" />
<filter-element type="OBJECT" id="privilege" selected="true" />
<user-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="false" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</user-schema>
<public-schema>
<filter-element type="OBJECT" id="table" selected="false" />
<filter-element type="OBJECT" id="view" selected="false" />
<filter-element type="OBJECT" id="materialized view" selected="false" />
<filter-element type="OBJECT" id="index" selected="false" />
<filter-element type="OBJECT" id="constraint" selected="false" />
<filter-element type="OBJECT" id="trigger" selected="false" />
<filter-element type="OBJECT" id="synonym" selected="false" />
<filter-element type="OBJECT" id="sequence" selected="false" />
<filter-element type="OBJECT" id="procedure" selected="false" />
<filter-element type="OBJECT" id="function" selected="false" />
<filter-element type="OBJECT" id="package" selected="false" />
<filter-element type="OBJECT" id="type" selected="false" />
<filter-element type="OBJECT" id="dimension" selected="false" />
<filter-element type="OBJECT" id="cluster" selected="false" />
<filter-element type="OBJECT" id="dblink" selected="false" />
</public-schema>
<any-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</any-schema>
</basic-filter>
<extended-filter>
<filter-element type="RESERVED_WORD" id="keyword" selected="true" />
<filter-element type="RESERVED_WORD" id="function" selected="true" />
<filter-element type="RESERVED_WORD" id="parameter" selected="true" />
<filter-element type="RESERVED_WORD" id="datatype" selected="true" />
<filter-element type="RESERVED_WORD" id="exception" selected="true" />
<filter-element type="OBJECT" id="schema" selected="true" />
<filter-element type="OBJECT" id="user" selected="true" />
<filter-element type="OBJECT" id="role" selected="true" />
<filter-element type="OBJECT" id="privilege" selected="true" />
<user-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</user-schema>
<public-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</public-schema>
<any-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</any-schema>
</extended-filter>
</filters>
<sorting enabled="true">
<sorting-element type="RESERVED_WORD" id="keyword" />
<sorting-element type="RESERVED_WORD" id="datatype" />
<sorting-element type="OBJECT" id="column" />
<sorting-element type="OBJECT" id="table" />
<sorting-element type="OBJECT" id="view" />
<sorting-element type="OBJECT" id="materialized view" />
<sorting-element type="OBJECT" id="index" />
<sorting-element type="OBJECT" id="constraint" />
<sorting-element type="OBJECT" id="trigger" />
<sorting-element type="OBJECT" id="synonym" />
<sorting-element type="OBJECT" id="sequence" />
<sorting-element type="OBJECT" id="procedure" />
<sorting-element type="OBJECT" id="function" />
<sorting-element type="OBJECT" id="package" />
<sorting-element type="OBJECT" id="type" />
<sorting-element type="OBJECT" id="dimension" />
<sorting-element type="OBJECT" id="cluster" />
<sorting-element type="OBJECT" id="dblink" />
<sorting-element type="OBJECT" id="schema" />
<sorting-element type="OBJECT" id="role" />
<sorting-element type="OBJECT" id="user" />
<sorting-element type="RESERVED_WORD" id="function" />
<sorting-element type="RESERVED_WORD" id="parameter" />
</sorting>
<format>
<enforce-code-style-case value="true" />
</format>
</code-completion-settings>
<execution-engine-settings>
<statement-execution>
<fetch-block-size value="100" />
<execution-timeout value="20" />
<debug-execution-timeout value="600" />
<focus-result value="false" />
<prompt-execution value="false" />
</statement-execution>
<script-execution>
<command-line-interfaces />
<execution-timeout value="300" />
</script-execution>
<method-execution>
<execution-timeout value="30" />
<debug-execution-timeout value="600" />
<parameter-history-size value="10" />
</method-execution>
</execution-engine-settings>
<operation-settings>
<transactions>
<uncommitted-changes>
<on-project-close value="ASK" />
<on-disconnect value="ASK" />
<on-autocommit-toggle value="ASK" />
</uncommitted-changes>
<multiple-uncommitted-changes>
<on-commit value="ASK" />
<on-rollback value="ASK" />
</multiple-uncommitted-changes>
</transactions>
<session-browser>
<disconnect-session value="ASK" />
<kill-session value="ASK" />
<reload-on-filter-change value="false" />
</session-browser>
<compiler>
<compile-type value="KEEP" />
<compile-dependencies value="ASK" />
<always-show-controls value="false" />
</compiler>
<debugger>
<debugger-type value="ASK" />
<use-generic-runners value="true" />
</debugger>
</operation-settings>
<ddl-file-settings>
<extensions>
<mapping file-type-id="VIEW" extensions="vw" />
<mapping file-type-id="TRIGGER" extensions="trg" />
<mapping file-type-id="PROCEDURE" extensions="prc" />
<mapping file-type-id="FUNCTION" extensions="fnc" />
<mapping file-type-id="PACKAGE" extensions="pkg" />
<mapping file-type-id="PACKAGE_SPEC" extensions="pks" />
<mapping file-type-id="PACKAGE_BODY" extensions="pkb" />
<mapping file-type-id="TYPE" extensions="tpe" />
<mapping file-type-id="TYPE_SPEC" extensions="tps" />
<mapping file-type-id="TYPE_BODY" extensions="tpb" />
</extensions>
<general>
<lookup-ddl-files value="true" />
<create-ddl-files value="false" />
<synchronize-ddl-files value="true" />
<use-qualified-names value="false" />
<make-scripts-rerunnable value="true" />
</general>
</ddl-file-settings>
<general-settings>
<regional-settings>
<date-format value="MEDIUM" />
<number-format value="UNGROUPED" />
<locale value="SYSTEM_DEFAULT" />
<use-custom-formats value="false" />
</regional-settings>
<environment>
<environment-types>
<environment-type id="development" name="Development" description="Development environment" color="-2430209/-12296320" readonly-code="false" readonly-data="false" />
<environment-type id="integration" name="Integration" description="Integration environment" color="-2621494/-12163514" readonly-code="true" readonly-data="false" />
<environment-type id="production" name="Production" description="Productive environment" color="-11574/-10271420" readonly-code="true" readonly-data="true" />
<environment-type id="other" name="Other" description="" color="-1576/-10724543" readonly-code="false" readonly-data="false" />
</environment-types>
<visibility-settings>
<connection-tabs value="true" />
<dialog-headers value="true" />
<object-editor-tabs value="true" />
<script-editor-tabs value="false" />
<execution-result-tabs value="true" />
</visibility-settings>
</environment>
</general-settings>
</component>
<component name="DBNavigator.Project.StatementExecutionManager">
<execution-variables />
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/jdk1.8.0_131.iml" filepath="$PROJECT_DIR$/jdk1.8.0_131.iml" />
</modules>
</component>
</project>

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="eef8024d-df1d-4b97-bc65-47cd7c855c1e" name="Default Changelist" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="GitToolBoxStore">
<option name="projectConfigVersion" value="2" />
</component>
<component name="MavenImportPreferences">
<option name="generalSettings">
<MavenGeneralSettings>
<option name="mavenHome" value="E:\frameworks\apache-maven-3.6.3" />
<option name="userSettingsFile" value="E:\frameworks\apache-maven-3.6.3\conf\settings.xml" />
</MavenGeneralSettings>
</option>
</component>
<component name="ProjectId" id="1qV1OzhKM3dtPDagywZ9Up9fkuo" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="aspect.path.notification.shown" value="true" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/../../../../my_java/AI_Study" />
<property name="project.structure.last.edited" value="Libraries" />
<property name="project.structure.proportion" value="0.0" />
<property name="project.structure.side.proportion" value="0.0" />
<property name="settings.editor.selected.configurable" value="preferences.pluginManager" />
<property name="vue.rearranger.settings.migration" value="true" />
</component>
<component name="RunManager">
<configuration default="true" type="Application" factoryName="Application">
<option name="PROGRAM_PARAMETERS" value="Jianliang" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="eef8024d-df1d-4b97-bc65-47cd7c855c1e" name="Default Changelist" comment="" />
<created>1617149915487</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1617149915487</updated>
<workItem from="1617149916818" duration="50000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
</project>

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="CheckStyle-IDEA-Module">
<option name="configuration">
<map />
</option>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -0,0 +1,90 @@
/*
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
#ifndef _DEFINES_H
#define _DEFINES_H
#include "java.h"
/*
* This file contains commonly defined constants used only by main.c
* and should not be included by another file.
*/
#ifndef FULL_VERSION
/* make sure the compilation fails */
#error "FULL_VERSION must be defined"
#endif
#if defined(JDK_MAJOR_VERSION) && defined(JDK_MINOR_VERSION)
#define DOT_VERSION JDK_MAJOR_VERSION "." JDK_MINOR_VERSION
#else
/* make sure the compilation fails */
#error "JDK_MAJOR_VERSION and JDK_MINOR_VERSION must be defined"
#endif
#ifdef JAVA_ARGS
static const char* const_progname = "java";
static const char* const_jargs[] = JAVA_ARGS;
/*
* ApplicationHome is prepended to each of these entries; the resulting
* strings are concatenated (separated by PATH_SEPARATOR) and used as the
* value of -cp option to the launcher.
*/
#ifndef APP_CLASSPATH
#define APP_CLASSPATH { "/lib/tools.jar", "/classes" }
#endif /* APP_CLASSPATH */
static const char* const_appclasspath[] = APP_CLASSPATH;
#else /* !JAVA_ARGS */
#ifdef PROGNAME
static const char* const_progname = PROGNAME;
#else
static char* const_progname = NULL;
#endif
static const char** const_jargs = NULL;
static const char** const_appclasspath = NULL;
#endif /* JAVA_ARGS */
#ifdef LAUNCHER_NAME
static const char* const_launcher = LAUNCHER_NAME;
#else /* LAUNCHER_NAME */
static char* const_launcher = NULL;
#endif /* LAUNCHER_NAME */
#ifdef EXPAND_CLASSPATH_WILDCARDS
static const jboolean const_cpwildcard = JNI_TRUE;
#else
static const jboolean const_cpwildcard = JNI_FALSE;
#endif /* EXPAND_CLASSPATH_WILDCARDS */
#if defined(NEVER_ACT_AS_SERVER_CLASS_MACHINE)
static const jint const_ergo_class = NEVER_SERVER_CLASS;
#elif defined(ALWAYS_ACT_AS_SERVER_CLASS_MACHINE)
static const jint const_ergo_class = ALWAYS_SERVER_CLASS;
#else
static const jint const_ergo_class = DEFAULT_POLICY;
#endif /* NEVER_ACT_AS_SERVER_CLASS_MACHINE */
#endif /*_DEFINES_H */

@ -0,0 +1,107 @@
/*
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
/*
* This file primarily consists of all the error and warning messages, that
* are used in JLI_ReportErrorMessage. All message must be defined here, in
* order to help with localizing the messages.
*/
#ifndef _EMESSAGES_H
#define _EMESSAGES_H
#define GEN_ERROR "Error: A fatal exception has occurred. Program will exit."
#define JNI_ERROR "Error: A JNI error has occurred, please check your installation and try again"
#define JNI_ERROR1 "Error: can't find JNI interfaces in: %s"
#define ARG_WARN "Warning: %s option is no longer supported."
#define ARG_ERROR1 "Error: %s requires class path specification"
#define ARG_ERROR2 "Error: %s requires jar file specification"
#define ARG_ERROR3 "Error: The -J option should not be followed by a space."
#define JVM_ERROR1 "Error: Could not create the Java Virtual Machine.\n" GEN_ERROR
#define JVM_ERROR2 "Error: Could not detach main thread.\n" JNI_ERROR
#define JVM_ERROR3 "Error: SPARC V8 processor detected; Required V9 processors or better.\nUse JDK5 client compiler for V8 processors.\n" JVM_ERROR1
#define JAR_ERROR1 "Error: Failed to load Main-Class manifest attribute from\n%s\n%s"
#define JAR_ERROR2 "Error: Unable to access jarfile %s"
#define JAR_ERROR3 "Error: Invalid or corrupt jarfile %s"
#define CLS_ERROR1 "Error: Could not find the main class %s.\n" JNI_ERROR
#define CLS_ERROR2 "Error: Failed to load Main Class: %s\n%s"
#define CLS_ERROR3 "Error: No main method found in specified class.\n" GEN_ERROR
#define CLS_ERROR4 "Error: Main method not public\n" GEN_ERROR
#define CLS_ERROR5 "Error: main-class: attribute exceeds system limits of %d bytes\n" GEN_ERROR
#define CFG_WARN1 "Warning: %s VM not supported; %s VM will be used"
#define CFG_WARN2 "Warning: No leading - on line %d of `%s'"
#define CFG_WARN3 "Warning: Missing VM type on line %d of `%s'"
#define CFG_WARN4 "Warning: Missing server class VM on line %d of `%s'"
#define CFG_WARN5 "Warning: Unknown VM type on line %d of `%s'"
#define CFG_ERROR1 "Error: Corrupt jvm.cfg file; cycle in alias list."
#define CFG_ERROR2 "Error: Unable to resolve VM alias %s"
#define CFG_ERROR3 "Error: %s VM not supported"
#define CFG_ERROR4 "Error: Unable to locate JRE meeting specification \"%s\""
#define CFG_ERROR5 "Error: Could not determine application home."
#define CFG_ERROR6 "Error: could not open `%s'"
#define CFG_ERROR7 "Error: no known VMs. (check for corrupt jvm.cfg file)"
#define CFG_ERROR8 "Error: missing `%s' JVM at `%s'.\nPlease install or use the JRE or JDK that contains these missing components."
#define CFG_ERROR9 "Error: could not determine JVM type."
#define SPC_ERROR1 "Error: Syntax error in version specification \"%s\""
#define JRE_ERROR1 "Error: Could not find Java SE Runtime Environment."
#define JRE_ERROR2 "Error: This Java instance does not support a %d-bit JVM.\nPlease install the desired version."
#define JRE_ERROR3 "Error: Improper value at line %d."
#define JRE_ERROR4 "Error: trying to exec %s.\nCheck if file exists and permissions are set correctly."
#define JRE_ERROR5 "Error: Failed to start a %d-bit JVM process from a %d-bit JVM."
#define JRE_ERROR6 "Error: Verify all necessary Java SE components have been installed.\n(Solaris SPARC 64-bit components must be installed after 32-bit components.)"
#define JRE_ERROR7 "Error: Either 64-bit processes are not supported by this platform\nor the 64-bit components have not been installed."
#define JRE_ERROR8 "Error: could not find "
#define JRE_ERROR9 "Error: Unable to resolve %s"
#define JRE_ERROR10 "Error: Unable to resolve current executable"
#define JRE_ERROR11 "Error: Path length exceeds maximum length (PATH_MAX)"
#define JRE_ERROR12 "Error: Exec of %s failed"
#define JRE_ERROR13 "Error: String processing operation failed"
#define DLL_ERROR1 "Error: dl failure on line %d"
#define DLL_ERROR2 "Error: failed %s, because %s"
#define DLL_ERROR3 "Error: could not find executable %s"
#define DLL_ERROR4 "Error: loading: %s"
#define REG_ERROR1 "Error: opening registry key '%s'"
#define REG_ERROR2 "Error: Failed reading value of registry key:\n\t%s\\CurrentVersion"
#define REG_ERROR3 "Error: Registry key '%s'\\CurrentVersion'\nhas value '%s', but '%s' is required."
#define REG_ERROR4 "Failed reading value of registry key:\n\t%s\\%s\\JavaHome"
#define SYS_ERROR1 "Error: CreateProcess(%s, ...) failed:"
#define SYS_ERROR2 "Error: WaitForSingleObject() failed."
#endif /* _EMESSAGES_H */

@ -0,0 +1,309 @@
/*
* Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
#ifndef _JAVA_H_
#define _JAVA_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <jni.h>
#include <jvm.h>
/*
* Get system specific defines.
*/
#include "emessages.h"
#include "java_md.h"
#include "jli_util.h"
#include "manifest_info.h"
#include "version_comp.h"
#include "wildcard.h"
#include "splashscreen.h"
# define KB (1024UL)
# define MB (1024UL * KB)
# define GB (1024UL * MB)
#define CURRENT_DATA_MODEL (CHAR_BIT * sizeof(void*))
/*
* The following environment variable is used to influence the behavior
* of the jre exec'd through the SelectVersion routine. The command line
* options which specify the version are not passed to the exec'd version,
* because that jre may be an older version which wouldn't recognize them.
* This environment variable is known to this (and later) version and serves
* to suppress the version selection code. This is not only for efficiency,
* but also for correctness, since any command line options have been
* removed which would cause any value found in the manifest to be used.
* This would be incorrect because the command line options are defined
* to take precedence.
*
* The value associated with this environment variable is the MainClass
* name from within the executable jar file (if any). This is strictly a
* performance enhancement to avoid re-reading the jar file manifest.
*
*/
#define ENV_ENTRY "_JAVA_VERSION_SET"
#define SPLASH_FILE_ENV_ENTRY "_JAVA_SPLASH_FILE"
#define SPLASH_JAR_ENV_ENTRY "_JAVA_SPLASH_JAR"
/*
* Pointers to the needed JNI invocation API, initialized by LoadJavaVM.
*/
typedef jint (JNICALL *CreateJavaVM_t)(JavaVM **pvm, void **env, void *args);
typedef jint (JNICALL *GetDefaultJavaVMInitArgs_t)(void *args);
typedef jint (JNICALL *GetCreatedJavaVMs_t)(JavaVM **vmBuf, jsize bufLen, jsize *nVMs);
typedef struct {
CreateJavaVM_t CreateJavaVM;
GetDefaultJavaVMInitArgs_t GetDefaultJavaVMInitArgs;
GetCreatedJavaVMs_t GetCreatedJavaVMs;
} InvocationFunctions;
int
JLI_Launch(int argc, char ** argv, /* main argc, argc */
int jargc, const char** jargv, /* java args */
int appclassc, const char** appclassv, /* app classpath */
const char* fullversion, /* full version defined */
const char* dotversion, /* dot version defined */
const char* pname, /* program name */
const char* lname, /* launcher name */
jboolean javaargs, /* JAVA_ARGS */
jboolean cpwildcard, /* classpath wildcard */
jboolean javaw, /* windows-only javaw */
jint ergo_class /* ergnomics policy */
);
/*
* Prototypes for launcher functions in the system specific java_md.c.
*/
jboolean
LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn);
void
GetXUsagePath(char *buf, jint bufsize);
jboolean
GetApplicationHome(char *buf, jint bufsize);
#define GetArch() GetArchPath(CURRENT_DATA_MODEL)
/*
* Different platforms will implement this, here
* pargc is a pointer to the original argc,
* pargv is a pointer to the original argv,
* jrepath is an accessible path to the jre as determined by the call
* so_jrepath is the length of the buffer jrepath
* jvmpath is an accessible path to the jvm as determined by the call
* so_jvmpath is the length of the buffer jvmpath
*/
void CreateExecutionEnvironment(int *argc, char ***argv,
char *jrepath, jint so_jrepath,
char *jvmpath, jint so_jvmpath,
char *jvmcfg, jint so_jvmcfg);
/* Reports an error message to stderr or a window as appropriate. */
void JLI_ReportErrorMessage(const char * message, ...);
/* Reports a system error message to stderr or a window */
void JLI_ReportErrorMessageSys(const char * message, ...);
/* Reports an error message only to stderr. */
void JLI_ReportMessage(const char * message, ...);
/*
* Reports an exception which terminates the vm to stderr or a window
* as appropriate.
*/
void JLI_ReportExceptionDescription(JNIEnv * env);
void PrintMachineDependentOptions();
const char *jlong_format_specifier();
/*
* Block current thread and continue execution in new thread
*/
int ContinueInNewThread0(int (JNICALL *continuation)(void *),
jlong stack_size, void * args);
/* sun.java.launcher.* platform properties. */
void SetJavaLauncherPlatformProps(void);
void SetJavaCommandLineProp(char* what, int argc, char** argv);
void SetJavaLauncherProp(void);
/*
* Functions defined in java.c and used in java_md.c.
*/
jint ReadKnownVMs(const char *jvmcfg, jboolean speculative);
char *CheckJvmType(int *argc, char ***argv, jboolean speculative);
void AddOption(char *str, void *info);
enum ergo_policy {
DEFAULT_POLICY = 0,
NEVER_SERVER_CLASS,
ALWAYS_SERVER_CLASS
};
const char* GetProgramName();
const char* GetDotVersion();
const char* GetFullVersion();
jboolean IsJavaArgs();
jboolean IsJavaw();
jint GetErgoPolicy();
jboolean ServerClassMachine();
int ContinueInNewThread(InvocationFunctions* ifn, jlong threadStackSize,
int argc, char** argv,
int mode, char *what, int ret);
int JVMInit(InvocationFunctions* ifn, jlong threadStackSize,
int argc, char** argv,
int mode, char *what, int ret);
/*
* Initialize platform specific settings
*/
void InitLauncher(jboolean javaw);
/*
* For MacOSX and Windows/Unix compatibility we require these
* entry points, some of them may be stubbed out on Windows/Unixes.
*/
void PostJVMInit(JNIEnv *env, jstring mainClass, JavaVM *vm);
void ShowSplashScreen();
void RegisterThread();
/*
* this method performs additional platform specific processing and
* should return JNI_TRUE to indicate the argument has been consumed,
* otherwise returns JNI_FALSE to allow the calling logic to further
* process the option.
*/
jboolean ProcessPlatformOption(const char *arg);
/*
* This allows for finding classes from the VM's bootstrap class loader directly,
* FindClass uses the application class loader internally, this will cause
* unnecessary searching of the classpath for the required classes.
*
*/
typedef jclass (JNICALL FindClassFromBootLoader_t(JNIEnv *env,
const char *name));
jclass FindBootStrapClass(JNIEnv *env, const char *classname);
jobjectArray CreateApplicationArgs(JNIEnv *env, char **strv, int argc);
jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc);
jclass GetLauncherHelperClass(JNIEnv *env);
int JNICALL JavaMain(void * args); /* entry point */
enum LaunchMode { // cf. sun.launcher.LauncherHelper
LM_UNKNOWN = 0,
LM_CLASS,
LM_JAR
};
static const char *launchModeNames[]
= { "Unknown", "Main class", "JAR file" };
typedef struct {
int argc;
char **argv;
int mode;
char *what;
InvocationFunctions ifn;
} JavaMainArgs;
#define NULL_CHECK_RETURN_VALUE(NCRV_check_pointer, NCRV_return_value) \
do { \
if ((NCRV_check_pointer) == NULL) { \
JLI_ReportErrorMessage(JNI_ERROR); \
return NCRV_return_value; \
} \
} while (JNI_FALSE)
#define NULL_CHECK0(NC0_check_pointer) \
NULL_CHECK_RETURN_VALUE(NC0_check_pointer, 0)
#define NULL_CHECK(NC_check_pointer) \
NULL_CHECK_RETURN_VALUE(NC_check_pointer, )
#define CHECK_EXCEPTION_RETURN() \
do { \
if ((*env)->ExceptionOccurred(env)) { \
return; \
} \
} while (JNI_FALSE)
/*
* For JNI calls :
* - check for thrown exceptions
* - check for null return
*
* JNI calls can return null and/or throw an exception. Check for these.
*
* : CHECK_JNI_RETURN_EXCEPTION()
* return the specified RETURNVALUE if exception was generated
* : CHECK_JNI_RETURN_0(JNISTATEMENT) : check if JNISTATEMENT was successful, return 0 if not
* : CHECK_JNI_RETURN_VOID(JNISTATEMENT) : check if JNISTATEMENT was successful, return void if not
* : CHECK_JNI_RETURN_VALUE(JNISTATEMENT,n) : check if JNISTATEMENT was successful, return n if not
*
* These macros need at least one parameter, the JNI statement [ JNISTATEMENT ].
*
* E.G.: check the JNI statement, and specify a value to return if a failure was detected.
*
* CHECK_JNI_RETURN_VALUE(str = (*env)->CallStaticObjectMethod(env, cls,
* makePlatformStringMID, USE_STDERR, ary), -1);
*/
#define RETURNVOID return
#define RETURN0 return 0
#define RETURN(N) return (N)
#define CHECK_JNI_RETURN_EXCEPTION(RETURNVALUE) \
if ((((*env)->ExceptionOccurred(env))!=NULL)) { \
RETURNVALUE; \
}
#define CHECK_JNI_RETURN_0(JNISTATEMENT) \
CHECK_JNI_RETURN_EXCEPTION(RETURN0); \
NULL_CHECK0(JNISTATEMENT);
#define CHECK_JNI_RETURN_VOID(JNISTATEMENT) \
CHECK_JNI_RETURN_EXCEPTION(RETURNVOID); \
NULL_CHECK(JNISTATEMENT);
#define CHECK_JNI_RETURN_VALUE(JNISTATEMENT, NCRV_return_value) \
CHECK_JNI_RETURN_EXCEPTION(RETURN(NCRV_return_value)); \
NULL_CHECK_RETURN_VALUE(JNISTATEMENT, NCRV_return_value);
#endif /* _JAVA_H_ */

@ -0,0 +1,57 @@
/*
* Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
#ifndef JAVA_MD_H
#define JAVA_MD_H
#include <jni.h>
#include <windows.h>
#include <io.h>
#include "manifest_info.h"
#include "jli_util.h"
#define PATH_SEPARATOR ';'
#define FILESEP "\\"
#define FILE_SEPARATOR '\\'
#define IS_FILE_SEPARATOR(c) ((c) == '\\' || (c) == '/')
#define MAXPATHLEN MAX_PATH
#define MAXNAMELEN MAX_PATH
/*
* Support for doing cheap, accurate interval timing.
*/
extern jlong CounterGet(void);
extern jlong Counter2Micros(jlong counts);
/*
* Function prototypes.
*/
char *LocateJRE(manifest_info *info);
void ExecJRE(char *jre, char **argv);
int UnsetEnv(char *name);
#endif /* JAVA_MD_H */

@ -0,0 +1,121 @@
/*
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
#include <stdio.h>
#include <string.h>
#include <jni.h>
#include "jli_util.h"
/*
* Returns a pointer to a block of at least 'size' bytes of memory.
* Prints error message and exits if the memory could not be allocated.
*/
void *
JLI_MemAlloc(size_t size)
{
void *p = malloc(size);
if (p == 0) {
perror("malloc");
exit(1);
}
return p;
}
/*
* Equivalent to realloc(size).
* Prints error message and exits if the memory could not be reallocated.
*/
void *
JLI_MemRealloc(void *ptr, size_t size)
{
void *p = realloc(ptr, size);
if (p == 0) {
perror("realloc");
exit(1);
}
return p;
}
/*
* Wrapper over strdup(3C) which prints an error message and exits if memory
* could not be allocated.
*/
char *
JLI_StringDup(const char *s1)
{
char *s = strdup(s1);
if (s == NULL) {
perror("strdup");
exit(1);
}
return s;
}
/*
* Very equivalent to free(ptr).
* Here to maintain pairing with the above routines.
*/
void
JLI_MemFree(void *ptr)
{
free(ptr);
}
/*
* debug helpers we use
*/
static jboolean _launcher_debug = JNI_FALSE;
void
JLI_TraceLauncher(const char* fmt, ...)
{
va_list vl;
if (_launcher_debug != JNI_TRUE) return;
va_start(vl, fmt);
vprintf(fmt,vl);
va_end(vl);
}
void
JLI_SetTraceLauncher()
{
if (getenv(JLDEBUG_ENV_ENTRY) != 0) {
_launcher_debug = JNI_TRUE;
JLI_TraceLauncher("----%s----\n", JLDEBUG_ENV_ENTRY);
}
}
jboolean
JLI_IsTraceLauncher()
{
return _launcher_debug;
}
int
JLI_StrCCmp(const char *s1, const char* s2)
{
return JLI_StrNCmp(s1, s2, JLI_StrLen(s2));
}

@ -0,0 +1,105 @@
/*
* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
#ifndef _JLI_UTIL_H
#define _JLI_UTIL_H
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <jni.h>
#define JLDEBUG_ENV_ENTRY "_JAVA_LAUNCHER_DEBUG"
void *JLI_MemAlloc(size_t size);
void *JLI_MemRealloc(void *ptr, size_t size);
char *JLI_StringDup(const char *s1);
void JLI_MemFree(void *ptr);
int JLI_StrCCmp(const char *s1, const char* s2);
typedef struct {
char *arg;
jboolean has_wildcard;
} StdArg;
StdArg *JLI_GetStdArgs();
int JLI_GetStdArgc();
#define JLI_StrLen(p1) strlen((p1))
#define JLI_StrChr(p1, p2) strchr((p1), (p2))
#define JLI_StrRChr(p1, p2) strrchr((p1), (p2))
#define JLI_StrCmp(p1, p2) strcmp((p1), (p2))
#define JLI_StrNCmp(p1, p2, p3) strncmp((p1), (p2), (p3))
#define JLI_StrCat(p1, p2) strcat((p1), (p2))
#define JLI_StrCpy(p1, p2) strcpy((p1), (p2))
#define JLI_StrNCpy(p1, p2, p3) strncpy((p1), (p2), (p3))
#define JLI_StrStr(p1, p2) strstr((p1), (p2))
#define JLI_StrSpn(p1, p2) strspn((p1), (p2))
#define JLI_StrCSpn(p1, p2) strcspn((p1), (p2))
#define JLI_StrPBrk(p1, p2) strpbrk((p1), (p2))
#define JLI_StrTok(p1, p2) strtok((p1), (p2))
/* On Windows lseek() is in io.h rather than the location dictated by POSIX. */
#ifdef _WIN32
#include <windows.h>
#include <io.h>
#include <process.h>
#define JLI_StrCaseCmp(p1, p2) stricmp((p1), (p2))
#define JLI_StrNCaseCmp(p1, p2, p3) strnicmp((p1), (p2), (p3))
int JLI_Snprintf(char *buffer, size_t size, const char *format, ...);
void JLI_CmdToArgs(char *cmdline);
#define JLI_Lseek _lseeki64
#define JLI_PutEnv _putenv
#define JLI_GetPid _getpid
#else /* NIXES */
#include <unistd.h>
#include <strings.h>
#define JLI_StrCaseCmp(p1, p2) strcasecmp((p1), (p2))
#define JLI_StrNCaseCmp(p1, p2, p3) strncasecmp((p1), (p2), (p3))
#define JLI_Snprintf snprintf
#define JLI_PutEnv putenv
#define JLI_GetPid getpid
#ifdef __solaris__
#define JLI_Lseek llseek
#endif
#ifdef __linux__
#define _LARGFILE64_SOURCE
#define JLI_Lseek lseek64
#endif
#ifdef MACOSX
#define JLI_Lseek lseek
#endif
#ifdef _AIX
#define JLI_Lseek lseek
#endif
#endif /* _WIN32 */
/*
* Make launcher spit debug output.
*/
void JLI_TraceLauncher(const char* fmt, ...);
void JLI_SetTraceLauncher();
jboolean JLI_IsTraceLauncher();
#endif /* _JLI_UTIL_H */

@ -0,0 +1,134 @@
/*
* Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
/*
* This file contains the main entry point into the launcher code
* this is the only file which will be repeatedly compiled by other
* tools. The rest of the files will be linked in.
*/
#include "defines.h"
#ifdef _MSC_VER
#if _MSC_VER > 1400 && _MSC_VER < 1600
/*
* When building for Microsoft Windows, main has a dependency on msvcr??.dll.
*
* When using Visual Studio 2005 or 2008, that must be recorded in
* the [java,javaw].exe.manifest file.
*
* As of VS2010 (ver=1600), the runtimes again no longer need manifests.
*
* Reference:
* C:/Program Files/Microsoft SDKs/Windows/v6.1/include/crtdefs.h
*/
#include <crtassem.h>
#ifdef _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' " \
"name='" __LIBRARIES_ASSEMBLY_NAME_PREFIX ".CRT' " \
"version='" _CRT_ASSEMBLY_VERSION "' " \
"processorArchitecture='x86' " \
"publicKeyToken='" _VC_ASSEMBLY_PUBLICKEYTOKEN "'\"")
#endif /* _M_IX86 */
//This may not be necessary yet for the Windows 64-bit build, but it
//will be when that build environment is updated. Need to test to see
//if it is harmless:
#ifdef _M_AMD64
#pragma comment(linker,"/manifestdependency:\"type='win32' " \
"name='" __LIBRARIES_ASSEMBLY_NAME_PREFIX ".CRT' " \
"version='" _CRT_ASSEMBLY_VERSION "' " \
"processorArchitecture='amd64' " \
"publicKeyToken='" _VC_ASSEMBLY_PUBLICKEYTOKEN "'\"")
#endif /* _M_AMD64 */
#endif /* _MSC_VER > 1400 && _MSC_VER < 1600 */
#endif /* _MSC_VER */
/*
* Entry point.
*/
#ifdef JAVAW
char **__initenv;
int WINAPI
WinMain(HINSTANCE inst, HINSTANCE previnst, LPSTR cmdline, int cmdshow)
{
int margc;
char** margv;
const jboolean const_javaw = JNI_TRUE;
__initenv = _environ;
#else /* JAVAW */
int
main(int argc, char **argv)
{
int margc;
char** margv;
const jboolean const_javaw = JNI_FALSE;
#endif /* JAVAW */
#ifdef _WIN32
{
int i = 0;
if (getenv(JLDEBUG_ENV_ENTRY) != NULL) {
printf("Windows original main args:\n");
for (i = 0 ; i < __argc ; i++) {
printf("wwwd_args[%d] = %s\n", i, __argv[i]);
}
}
}
JLI_CmdToArgs(GetCommandLine());
margc = JLI_GetStdArgc();
// add one more to mark the end
margv = (char **)JLI_MemAlloc((margc + 1) * (sizeof(char *)));
{
int i = 0;
StdArg *stdargs = JLI_GetStdArgs();
for (i = 0 ; i < margc ; i++) {
margv[i] = stdargs[i].arg;
}
margv[i] = NULL;
}
#else /* *NIXES */
margc = argc;
margv = argv;
#endif /* WIN32 */
return JLI_Launch(margc, margv,
sizeof(const_jargs) / sizeof(char *), const_jargs,
sizeof(const_appclasspath) / sizeof(char *), const_appclasspath,
FULL_VERSION,
DOT_VERSION,
(const_progname != NULL) ? const_progname : *margv,
(const_launcher != NULL) ? const_launcher : *margv,
(const_jargs != NULL) ? JNI_TRUE : JNI_FALSE,
const_cpwildcard, const_javaw, const_ergo_class);
}

@ -0,0 +1,187 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
#ifndef _MANIFEST_INFO_H
#define _MANIFEST_INFO_H
#include <sys/types.h>
/*
* Zip file header signatures
*/
#define SIGSIZ 4 /* size of all header signatures */
#define LOCSIG 0x04034b50L /* "PK\003\004" */
#define EXTSIG 0x08074b50L /* "PK\007\008" */
#define CENSIG 0x02014b50L /* "PK\001\002" */
#define ENDSIG 0x06054b50L /* "PK\005\006" */
#define ZIP64_ENDSIG 0x06064b50L /* "PK\006\006" */
#define ZIP64_LOCSIG 0x07064b50L /* "PK\006\007" */
/*
* Header sizes including signatures
*/
#define LOCHDR 30
#define EXTHDR 16
#define CENHDR 46
#define ENDHDR 22
#define ZIP64_ENDHDR 56 // ZIP64 end header size
#define ZIP64_LOCHDR 20 // ZIP64 end loc header size
#define ZIP64_EXTHDR 24 // EXT header size
#define ZIP64_EXTID 1 // Extra field Zip64 header ID
#define ZIP64_MAGICVAL 0xffffffffLL
#define ZIP64_MAGICCOUNT 0xffff
/*
* Header field access macros
*/
#define CH(b, n) (((unsigned char *)(b))[n])
#define SH(b, n) (CH(b, n) | (CH(b, n+1) << 8))
#define LG(b, n) ((SH(b, n) | (SH(b, n+2) << 16)) &0xffffffffUL)
#define LL(b, n) (((jlong)LG(b, n)) | (((jlong)LG(b, n+4)) << 32))
#define GETSIG(b) LG(b, 0)
/*
* Macros for getting local file (LOC) header fields
*/
#define LOCVER(b) SH(b, 4) /* version needed to extract */
#define LOCFLG(b) SH(b, 6) /* general purpose bit flags */
#define LOCHOW(b) SH(b, 8) /* compression method */
#define LOCTIM(b) LG(b, 10) /* modification time */
#define LOCCRC(b) LG(b, 14) /* crc of uncompressed data */
#define LOCSIZ(b) LG(b, 18) /* compressed data size */
#define LOCLEN(b) LG(b, 22) /* uncompressed data size */
#define LOCNAM(b) SH(b, 26) /* filename length */
#define LOCEXT(b) SH(b, 28) /* extra field length */
/*
* Macros for getting extra local (EXT) header fields
*/
#define EXTCRC(b) LG(b, 4) /* crc of uncompressed data */
#define EXTSIZ(b) LG(b, 8) /* compressed size */
#define EXTLEN(b) LG(b, 12) /* uncompressed size */
/*
* Macros for getting central directory header (CEN) fields
*/
#define CENVEM(b) SH(b, 4) /* version made by */
#define CENVER(b) SH(b, 6) /* version needed to extract */
#define CENFLG(b) SH(b, 8) /* general purpose bit flags */
#define CENHOW(b) SH(b, 10) /* compression method */
#define CENTIM(b) LG(b, 12) /* modification time */
#define CENCRC(b) LG(b, 16) /* crc of uncompressed data */
#define CENSIZ(b) LG(b, 20) /* compressed size */
#define CENLEN(b) LG(b, 24) /* uncompressed size */
#define CENNAM(b) SH(b, 28) /* length of filename */
#define CENEXT(b) SH(b, 30) /* length of extra field */
#define CENCOM(b) SH(b, 32) /* file comment length */
#define CENDSK(b) SH(b, 34) /* disk number start */
#define CENATT(b) SH(b, 36) /* internal file attributes */
#define CENATX(b) LG(b, 38) /* external file attributes */
#define CENOFF(b) LG(b, 42) /* offset of local header */
/*
* Macros for getting end of central directory header (END) fields
*/
#define ENDSUB(b) SH(b, 8) /* number of entries on this disk */
#define ENDTOT(b) SH(b, 10) /* total number of entries */
#define ENDSIZ(b) LG(b, 12) /* central directory size */
#define ENDOFF(b) LG(b, 16) /* central directory offset */
#define ENDCOM(b) SH(b, 20) /* size of zip file comment */
/*
* Macros for getting Zip64 end of central directory header fields
*/
#define ZIP64_ENDLEN(b) LL(b, 4) /* size of zip64 end of central dir */
#define ZIP64_ENDVEM(b) SH(b, 12) /* version made by */
#define ZIP64_ENDVER(b) SH(b, 14) /* version needed to extract */
#define ZIP64_ENDNMD(b) LG(b, 16) /* number of this disk */
#define ZIP64_ENDDSK(b) LG(b, 20) /* disk number of start */
#define ZIP64_ENDTOD(b) LL(b, 24) /* total number of entries on this disk */
#define ZIP64_ENDTOT(b) LL(b, 32) /* total number of entries */
#define ZIP64_ENDSIZ(b) LL(b, 40) /* central directory size in bytes */
#define ZIP64_ENDOFF(b) LL(b, 48) /* offset of first CEN header */
/*
* Macros for getting Zip64 end of central directory locator fields
*/
#define ZIP64_LOCDSK(b) LG(b, 4) /* disk number start */
#define ZIP64_LOCOFF(b) LL(b, 8) /* offset of zip64 end */
#define ZIP64_LOCTOT(b) LG(b, 16) /* total number of disks */
/*
* A comment of maximum length of 64kb can follow the END record. This
* is the furthest the END record can be from the end of the file.
*/
#define END_MAXLEN (0xFFFF + ENDHDR)
/*
* Supported compression methods.
*/
#define STORED 0
#define DEFLATED 8
/*
* Information from the CEN entry to inflate a file.
*/
typedef struct zentry { /* Zip file entry */
size_t isize; /* size of inflated data */
size_t csize; /* size of compressed data (zero if uncompressed) */
jlong offset; /* position of compressed data */
int how; /* compression method (if any) */
} zentry;
/*
* Information returned from the Manifest file by the ParseManifest() routine.
* Certainly (much) more could be returned, but this is the information
* currently of interest to the C based Java utilities (particularly the
* Java launcher).
*/
typedef struct manifest_info { /* Interesting fields from the Manifest */
char *manifest_version; /* Manifest-Version string */
char *main_class; /* Main-Class entry */
char *jre_version; /* Appropriate J2SE release spec */
char jre_restrict_search; /* Restricted JRE search */
char *splashscreen_image_file_name; /* splashscreen image file */
} manifest_info;
/*
* Attribute closure to provide to manifest_iterate.
*/
typedef void (*attribute_closure)(const char *name, const char *value,
void *user_data);
/*
* Function prototypes.
*/
int JLI_ParseManifest(char *jarfile, manifest_info *info);
void *JLI_JarUnpackFile(const char *jarfile, const char *filename,
int *size);
void JLI_FreeManifest(void);
int JLI_ManifestIterate(const char *jarfile, attribute_closure ac,
void *user_data);
#endif /* _MANIFEST_INFO_H */

@ -0,0 +1,698 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jli_util.h"
#include <zlib.h>
#include "manifest_info.h"
static char *manifest;
static const char *manifest_name = "META-INF/MANIFEST.MF";
/*
* Inflate the manifest file (or any file for that matter).
*
* fd: File descriptor of the jar file.
* entry: Contains the information necessary to perform the inflation
* (the compressed and uncompressed sizes and the offset in
* the file where the compressed data is located).
* size_out: Returns the size of the inflated file.
*
* Upon success, it returns a pointer to a NUL-terminated malloc'd buffer
* containing the inflated manifest file. When the caller is done with it,
* this buffer should be released by a call to free(). Upon failure,
* returns NULL.
*/
static char *
inflate_file(int fd, zentry *entry, int *size_out)
{
char *in;
char *out;
z_stream zs;
if (entry->csize == (size_t) -1 || entry->isize == (size_t) -1 )
return (NULL);
if (JLI_Lseek(fd, entry->offset, SEEK_SET) < (jlong)0)
return (NULL);
if ((in = malloc(entry->csize + 1)) == NULL)
return (NULL);
if ((size_t)(read(fd, in, (unsigned int)entry->csize)) != entry->csize) {
free(in);
return (NULL);
}
if (entry->how == STORED) {
*(char *)((size_t)in + entry->csize) = '\0';
if (size_out) {
*size_out = (int)entry->csize;
}
return (in);
} else if (entry->how == DEFLATED) {
zs.zalloc = (alloc_func)Z_NULL;
zs.zfree = (free_func)Z_NULL;
zs.opaque = (voidpf)Z_NULL;
zs.next_in = (Byte*)in;
zs.avail_in = (uInt)entry->csize;
if (inflateInit2(&zs, -MAX_WBITS) < 0) {
free(in);
return (NULL);
}
if ((out = malloc(entry->isize + 1)) == NULL) {
free(in);
return (NULL);
}
zs.next_out = (Byte*)out;
zs.avail_out = (uInt)entry->isize;
if (inflate(&zs, Z_PARTIAL_FLUSH) < 0) {
free(in);
free(out);
return (NULL);
}
*(char *)((size_t)out + entry->isize) = '\0';
free(in);
if (inflateEnd(&zs) < 0) {
free(out);
return (NULL);
}
if (size_out) {
*size_out = (int)entry->isize;
}
return (out);
}
free(in);
return (NULL);
}
static jboolean zip64_present = JNI_FALSE;
/*
* Checks to see if we have ZIP64 archive, and save
* the check for later use
*/
static int
haveZIP64(Byte *p) {
jlong cenlen, cenoff, centot;
cenlen = ENDSIZ(p);
cenoff = ENDOFF(p);
centot = ENDTOT(p);
zip64_present = (cenlen == ZIP64_MAGICVAL ||
cenoff == ZIP64_MAGICVAL ||
centot == ZIP64_MAGICCOUNT);
return zip64_present;
}
static jlong
find_end64(int fd, Byte *ep, jlong pos)
{
jlong end64pos;
jlong bytes;
if ((end64pos = JLI_Lseek(fd, pos - ZIP64_LOCHDR, SEEK_SET)) < (jlong)0)
return -1;
if ((bytes = read(fd, ep, ZIP64_LOCHDR)) < 0)
return -1;
if (GETSIG(ep) == ZIP64_LOCSIG)
return end64pos;
return -1;
}
/*
* A very little used routine to handle the case that zip file has
* a comment at the end. Believe it or not, the only way to find the
* END record is to walk backwards, byte by bloody byte looking for
* the END record signature.
*
* fd: File descriptor of the jar file.
* eb: Pointer to a buffer to receive a copy of the END header.
*
* Returns the offset of the END record in the file on success,
* -1 on failure.
*/
static jlong
find_end(int fd, Byte *eb)
{
jlong len;
jlong pos;
jlong flen;
int bytes;
Byte *cp;
Byte *endpos;
Byte *buffer;
/*
* 99.44% (or more) of the time, there will be no comment at the
* end of the zip file. Try reading just enough to read the END
* record from the end of the file, at this time we should also
* check to see if we have a ZIP64 archive.
*/
if ((pos = JLI_Lseek(fd, -ENDHDR, SEEK_END)) < (jlong)0)
return (-1);
if ((bytes = read(fd, eb, ENDHDR)) < 0)
return (-1);
if (GETSIG(eb) == ENDSIG) {
return haveZIP64(eb) ? find_end64(fd, eb, pos) : pos;
}
/*
* Shucky-Darn,... There is a comment at the end of the zip file.
*
* Allocate and fill a buffer with enough of the zip file
* to meet the specification for a maximal comment length.
*/
if ((flen = JLI_Lseek(fd, 0, SEEK_END)) < (jlong)0)
return (-1);
len = (flen < END_MAXLEN) ? flen : END_MAXLEN;
if (JLI_Lseek(fd, -len, SEEK_END) < (jlong)0)
return (-1);
if ((buffer = malloc(END_MAXLEN)) == NULL)
return (-1);
if ((bytes = read(fd, buffer, len)) < 0) {
free(buffer);
return (-1);
}
/*
* Search backwards from the end of file stopping when the END header
* signature is found. (The first condition of the "if" is just a
* fast fail, because the GETSIG macro isn't always cheap. The
* final condition protects against false positives.)
*/
endpos = &buffer[bytes];
for (cp = &buffer[bytes - ENDHDR]; cp >= &buffer[0]; cp--)
if ((*cp == (ENDSIG & 0xFF)) && (GETSIG(cp) == ENDSIG) &&
(cp + ENDHDR + ENDCOM(cp) == endpos)) {
(void) memcpy(eb, cp, ENDHDR);
free(buffer);
pos = flen - (endpos - cp);
return haveZIP64(eb) ? find_end64(fd, eb, pos) : pos;
}
free(buffer);
return (-1);
}
#define BUFSIZE (3 * 65536 + CENHDR + SIGSIZ)
#define MINREAD 1024
/*
* Computes and positions at the start of the CEN header, ie. the central
* directory, this will also return the offset if there is a zip file comment
* at the end of the archive, for most cases this would be 0.
*/
static jlong
compute_cen(int fd, Byte *bp)
{
int bytes;
Byte *p;
jlong base_offset;
jlong offset;
char buffer[MINREAD];
p = buffer;
/*
* Read the END Header, which is the starting point for ZIP files.
* (Clearly designed to make writing a zip file easier than reading
* one. Now isn't that precious...)
*/
if ((base_offset = find_end(fd, bp)) == -1) {
return (-1);
}
p = bp;
/*
* There is a historical, but undocumented, ability to allow for
* additional "stuff" to be prepended to the zip/jar file. It seems
* that this has been used to prepend an actual java launcher
* executable to the jar on Windows. Although this is just another
* form of statically linking a small piece of the JVM to the
* application, we choose to continue to support it. Note that no
* guarantees have been made (or should be made) to the customer that
* this will continue to work.
*
* Therefore, calculate the base offset of the zip file (within the
* expanded file) by assuming that the central directory is followed
* immediately by the end record.
*/
if (zip64_present) {
if ((offset = ZIP64_LOCOFF(p)) < (jlong)0) {
return -1;
}
if (JLI_Lseek(fd, offset, SEEK_SET) < (jlong) 0) {
return (-1);
}
if ((bytes = read(fd, buffer, MINREAD)) < 0) {
return (-1);
}
if (GETSIG(buffer) != ZIP64_ENDSIG) {
return -1;
}
if ((offset = ZIP64_ENDOFF(buffer)) < (jlong)0) {
return -1;
}
if (JLI_Lseek(fd, offset, SEEK_SET) < (jlong)0) {
return (-1);
}
p = buffer;
base_offset = base_offset - ZIP64_ENDSIZ(p) - ZIP64_ENDOFF(p) - ZIP64_ENDHDR;
} else {
base_offset = base_offset - ENDSIZ(p) - ENDOFF(p);
/*
* The END Header indicates the start of the Central Directory
* Headers. Remember that the desired Central Directory Header (CEN)
* will almost always be the second one and the first one is a small
* directory entry ("META-INF/"). Keep the code optimized for
* that case.
*
* Seek to the beginning of the Central Directory.
*/
if (JLI_Lseek(fd, base_offset + ENDOFF(p), SEEK_SET) < (jlong) 0) {
return (-1);
}
}
return base_offset;
}
/*
* Locate the manifest file with the zip/jar file.
*
* fd: File descriptor of the jar file.
* entry: To be populated with the information necessary to perform
* the inflation (the compressed and uncompressed sizes and
* the offset in the file where the compressed data is located).
*
* Returns zero upon success. Returns a negative value upon failure.
*
* The buffer for reading the Central Directory if the zip/jar file needs
* to be large enough to accommodate the largest possible single record
* and the signature of the next record which is:
*
* 3*2**16 + CENHDR + SIGSIZ
*
* Each of the three variable sized fields (name, comment and extension)
* has a maximum possible size of 64k.
*
* Typically, only a small bit of this buffer is used with bytes shuffled
* down to the beginning of the buffer. It is one thing to allocate such
* a large buffer and another thing to actually start faulting it in.
*
* In most cases, all that needs to be read are the first two entries in
* a typical jar file (META-INF and META-INF/MANIFEST.MF). Keep this factoid
* in mind when optimizing this code.
*/
static int
find_file(int fd, zentry *entry, const char *file_name)
{
int bytes;
int res;
int entry_size;
int read_size;
jlong base_offset;
Byte *p;
Byte *bp;
Byte *buffer;
Byte locbuf[LOCHDR];
if ((buffer = (Byte*)malloc(BUFSIZE)) == NULL) {
return(-1);
}
bp = buffer;
base_offset = compute_cen(fd, bp);
if (base_offset == -1) {
free(buffer);
return -1;
}
if ((bytes = read(fd, bp, MINREAD)) < 0) {
free(buffer);
return (-1);
}
p = bp;
/*
* Loop through the Central Directory Headers. Note that a valid zip/jar
* must have an ENDHDR (with ENDSIG) after the Central Directory.
*/
while (GETSIG(p) == CENSIG) {
/*
* If a complete header isn't in the buffer, shift the contents
* of the buffer down and refill the buffer. Note that the check
* for "bytes < CENHDR" must be made before the test for the entire
* size of the header, because if bytes is less than CENHDR, the
* actual size of the header can't be determined. The addition of
* SIGSIZ guarantees that the next signature is also in the buffer
* for proper loop termination.
*/
if (bytes < CENHDR) {
p = memmove(bp, p, bytes);
if ((res = read(fd, bp + bytes, MINREAD)) <= 0) {
free(buffer);
return (-1);
}
bytes += res;
}
entry_size = CENHDR + CENNAM(p) + CENEXT(p) + CENCOM(p);
if (bytes < entry_size + SIGSIZ) {
if (p != bp)
p = memmove(bp, p, bytes);
read_size = entry_size - bytes + SIGSIZ;
read_size = (read_size < MINREAD) ? MINREAD : read_size;
if ((res = read(fd, bp + bytes, read_size)) <= 0) {
free(buffer);
return (-1);
}
bytes += res;
}
/*
* Check if the name is the droid we are looking for; the jar file
* manifest. If so, build the entry record from the data found in
* the header located and return success.
*/
if ((size_t)CENNAM(p) == JLI_StrLen(file_name) &&
memcmp((p + CENHDR), file_name, JLI_StrLen(file_name)) == 0) {
if (JLI_Lseek(fd, base_offset + CENOFF(p), SEEK_SET) < (jlong)0) {
free(buffer);
return (-1);
}
if (read(fd, locbuf, LOCHDR) < 0) {
free(buffer);
return (-1);
}
if (GETSIG(locbuf) != LOCSIG) {
free(buffer);
return (-1);
}
entry->isize = CENLEN(p);
entry->csize = CENSIZ(p);
entry->offset = base_offset + CENOFF(p) + LOCHDR +
LOCNAM(locbuf) + LOCEXT(locbuf);
entry->how = CENHOW(p);
free(buffer);
return (0);
}
/*
* Point to the next entry and decrement the count of valid remaining
* bytes.
*/
bytes -= entry_size;
p += entry_size;
}
free(buffer);
return (-1); /* Fell off the end the loop without a Manifest */
}
/*
* Parse a Manifest file header entry into a distinct "name" and "value".
* Continuation lines are joined into a single "value". The documented
* syntax for a header entry is:
*
* header: name ":" value
*
* name: alphanum *headerchar
*
* value: SPACE *otherchar newline *continuation
*
* continuation: SPACE *otherchar newline
*
* newline: CR LF | LF | CR (not followed by LF)
*
* alphanum: {"A"-"Z"} | {"a"-"z"} | {"0"-"9"}
*
* headerchar: alphanum | "-" | "_"
*
* otherchar: any UTF-8 character except NUL, CR and LF
*
* Note that a manifest file may be composed of multiple sections,
* each of which may contain multiple headers.
*
* section: *header +newline
*
* nonempty-section: +header +newline
*
* (Note that the point of "nonempty-section" is unclear, because it isn't
* referenced elsewhere in the full specification for the Manifest file.)
*
* Arguments:
* lp pointer to a character pointer which points to the start
* of a valid header.
* name pointer to a character pointer which will be set to point
* to the name portion of the header (nul terminated).
* value pointer to a character pointer which will be set to point
* to the value portion of the header (nul terminated).
*
* Returns:
* 1 Successful parsing of an NV pair. lp is updated to point to the
* next character after the terminating newline in the string
* representing the Manifest file. name and value are updated to
* point to the strings parsed.
* 0 A valid end of section indicator was encountered. lp, name, and
* value are not modified.
* -1 lp does not point to a valid header. Upon return, the values of
* lp, name, and value are undefined.
*/
static int
parse_nv_pair(char **lp, char **name, char **value)
{
char *nl;
char *cp;
/*
* End of the section - return 0. The end of section condition is
* indicated by either encountering a blank line or the end of the
* Manifest "string" (EOF).
*/
if (**lp == '\0' || **lp == '\n' || **lp == '\r')
return (0);
/*
* Getting to here, indicates that *lp points to an "otherchar".
* Turn the "header" into a string on its own.
*/
nl = JLI_StrPBrk(*lp, "\n\r");
if (nl == NULL) {
nl = JLI_StrChr(*lp, (int)'\0');
} else {
cp = nl; /* For merging continuation lines */
if (*nl == '\r' && *(nl+1) == '\n')
*nl++ = '\0';
*nl++ = '\0';
/*
* Process any "continuation" line(s), by making them part of the
* "header" line. Yes, I know that we are "undoing" the NULs we
* just placed here, but continuation lines are the fairly rare
* case, so we shouldn't unnecessarily complicate the code above.
*
* Note that an entire continuation line is processed each iteration
* through the outer while loop.
*/
while (*nl == ' ') {
nl++; /* First character to be moved */
while (*nl != '\n' && *nl != '\r' && *nl != '\0')
*cp++ = *nl++; /* Shift string */
if (*nl == '\0')
return (-1); /* Error: newline required */
*cp = '\0';
if (*nl == '\r' && *(nl+1) == '\n')
*nl++ = '\0';
*nl++ = '\0';
}
}
/*
* Separate the name from the value;
*/
cp = JLI_StrChr(*lp, (int)':');
if (cp == NULL)
return (-1);
*cp++ = '\0'; /* The colon terminates the name */
if (*cp != ' ')
return (-1);
*cp++ = '\0'; /* Eat the required space */
*name = *lp;
*value = cp;
*lp = nl;
return (1);
}
/*
* Read the manifest from the specified jar file and fill in the manifest_info
* structure with the information found within.
*
* Error returns are as follows:
* 0 Success
* -1 Unable to open jarfile
* -2 Error accessing the manifest from within the jarfile (most likely
* a manifest is not present, or this isn't a valid zip/jar file).
*/
int
JLI_ParseManifest(char *jarfile, manifest_info *info)
{
int fd;
zentry entry;
char *lp;
char *name;
char *value;
int rc;
char *splashscreen_name = NULL;
if ((fd = open(jarfile, O_RDONLY
#ifdef O_LARGEFILE
| O_LARGEFILE /* large file mode */
#endif
#ifdef O_BINARY
| O_BINARY /* use binary mode on windows */
#endif
)) == -1) {
return (-1);
}
info->manifest_version = NULL;
info->main_class = NULL;
info->jre_version = NULL;
info->jre_restrict_search = 0;
info->splashscreen_image_file_name = NULL;
if (rc = find_file(fd, &entry, manifest_name) != 0) {
close(fd);
return (-2);
}
manifest = inflate_file(fd, &entry, NULL);
if (manifest == NULL) {
close(fd);
return (-2);
}
lp = manifest;
while ((rc = parse_nv_pair(&lp, &name, &value)) > 0) {
if (JLI_StrCaseCmp(name, "Manifest-Version") == 0)
info->manifest_version = value;
else if (JLI_StrCaseCmp(name, "Main-Class") == 0)
info->main_class = value;
else if (JLI_StrCaseCmp(name, "JRE-Version") == 0)
info->jre_version = value;
else if (JLI_StrCaseCmp(name, "JRE-Restrict-Search") == 0) {
if (JLI_StrCaseCmp(value, "true") == 0)
info->jre_restrict_search = 1;
} else if (JLI_StrCaseCmp(name, "Splashscreen-Image") == 0) {
info->splashscreen_image_file_name = value;
}
}
close(fd);
if (rc == 0)
return (0);
else
return (-2);
}
/*
* Opens the jar file and unpacks the specified file from its contents.
* Returns NULL on failure.
*/
void *
JLI_JarUnpackFile(const char *jarfile, const char *filename, int *size) {
int fd;
zentry entry;
void *data = NULL;
if ((fd = open(jarfile, O_RDONLY
#ifdef O_LARGEFILE
| O_LARGEFILE /* large file mode */
#endif
#ifdef O_BINARY
| O_BINARY /* use binary mode on windows */
#endif
)) == -1) {
return NULL;
}
if (find_file(fd, &entry, filename) == 0) {
data = inflate_file(fd, &entry, size);
}
close(fd);
return (data);
}
/*
* Specialized "free" function.
*/
void
JLI_FreeManifest()
{
if (manifest)
free(manifest);
}
/*
* Iterate over the manifest of the specified jar file and invoke the provided
* closure function for each attribute encountered.
*
* Error returns are as follows:
* 0 Success
* -1 Unable to open jarfile
* -2 Error accessing the manifest from within the jarfile (most likely
* this means a manifest is not present, or it isn't a valid zip/jar file).
*/
int
JLI_ManifestIterate(const char *jarfile, attribute_closure ac, void *user_data)
{
int fd;
zentry entry;
char *mp; /* manifest pointer */
char *lp; /* pointer into manifest, updated during iteration */
char *name;
char *value;
int rc;
if ((fd = open(jarfile, O_RDONLY
#ifdef O_LARGEFILE
| O_LARGEFILE /* large file mode */
#endif
#ifdef O_BINARY
| O_BINARY /* use binary mode on windows */
#endif
)) == -1) {
return (-1);
}
if (rc = find_file(fd, &entry, manifest_name) != 0) {
close(fd);
return (-2);
}
mp = inflate_file(fd, &entry, NULL);
if (mp == NULL) {
close(fd);
return (-2);
}
lp = mp;
while ((rc = parse_nv_pair(&lp, &name, &value)) > 0) {
(*ac)(name, value, user_data);
}
free(mp);
close(fd);
return (rc == 0) ? 0 : -2;
}

@ -0,0 +1,34 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
int DoSplashLoadMemory(void* pdata, int size); /* requires preloading the file */
int DoSplashLoadFile(const char* filename);
void DoSplashInit(void);
void DoSplashClose(void);
void DoSplashSetFileJarName(const char* fileName, const char* jarName);
void DoSplashSetScaleFactor(float scaleFactor);
char* DoSplashGetScaledImageName(const char* jarName, const char* fileName,
float* scaleFactor);

@ -0,0 +1,90 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
#include <stdio.h>
#include "splashscreen.h"
extern void* SplashProcAddress(const char* name); /* in java_md.c */
/*
* Prototypes of pointers to functions in splashscreen shared lib
*/
typedef int (*SplashLoadMemory_t)(void* pdata, int size);
typedef int (*SplashLoadFile_t)(const char* filename);
typedef void (*SplashInit_t)(void);
typedef void (*SplashClose_t)(void);
typedef void (*SplashSetFileJarName_t)(const char* fileName,
const char* jarName);
typedef void (*SplashSetScaleFactor_t)(float scaleFactor);
typedef char* (*SplashGetScaledImageName_t)(const char* fileName,
const char* jarName, float* scaleFactor);
/*
* This macro invokes a function from the shared lib.
* it locates a function with SplashProcAddress on demand.
* if SplashProcAddress fails, def value is returned.
*
* it is further wrapped with INVOKEV (works with functions which return
* void and INVOKE (for all other functions). INVOKEV looks a bit ugly,
* that's due being unable to return a value of type void in C. INVOKEV
* works around this by using semicolon instead of return operator.
*/
#define _INVOKE(name,def,ret) \
static void* proc = NULL; \
if (!proc) { proc = SplashProcAddress(#name); } \
if (!proc) { return def; } \
ret ((name##_t)proc)
#define INVOKE(name,def) _INVOKE(name,def,return)
#define INVOKEV(name) _INVOKE(name, ,;)
int DoSplashLoadMemory(void* pdata, int size) {
INVOKE(SplashLoadMemory, NULL)(pdata, size);
}
int DoSplashLoadFile(const char* filename) {
INVOKE(SplashLoadFile, NULL)(filename);
}
void DoSplashInit(void) {
INVOKEV(SplashInit)();
}
void DoSplashClose(void) {
INVOKEV(SplashClose)();
}
void DoSplashSetFileJarName(const char* fileName, const char* jarName) {
INVOKEV(SplashSetFileJarName)(fileName, jarName);
}
void DoSplashSetScaleFactor(float scaleFactor) {
INVOKEV(SplashSetScaleFactor)(scaleFactor);
}
char* DoSplashGetScaledImageName(const char* fileName, const char* jarName,
float* scaleFactor) {
INVOKE(SplashGetScaledImageName, NULL)(fileName, jarName, scaleFactor);
}

@ -0,0 +1,357 @@
/*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include "jni.h"
#include "jli_util.h"
#include "version_comp.h"
/*
* A collection of useful strings. One should think of these as #define
* entries, but actual strings can be more efficient (with many compilers).
*/
static const char *separators = ".-_";
static const char *zero_string = "0";
/*
* Validate a string as parsable as a "Java int". If so parsable,
* return true (non-zero) and store the numeric value at the address
* passed in as "value"; otherwise return false (zero).
*
* Note that the maximum allowable value is 2147483647 as defined by
* the "Java Language Specification" which precludes the use of native
* conversion routines which may have other limits.
*
* Also note that we don't have to worry about the alternate maximum
* allowable value of 2147483648 because it is only allowed after
* the unary negation operator and this grammar doesn't have one
* of those.
*
* Finally, note that a value which exceeds the maximum jint value will
* return false (zero). This results in the otherwise purely numeric
* string being compared as a string of characters (as per the spec.)
*/
static int
isjavaint(const char *s, jint *value)
{
jlong sum = 0;
jint digit;
while (*s != '\0')
if (isdigit(*s)) {
digit = (jint)((int)(*s++) - (int)('0'));
sum = (sum * 10) + digit;
if (sum > 2147483647)
return (0); /* Overflows jint (but not jlong) */
} else
return (0);
*value = (jint)sum;
return (1);
}
/*
* Modeled after strcmp(), compare two strings (as in the grammar defined
* in Appendix A of JSR 56). If both strings can be interpreted as
* Java ints, do a numeric comparison, else it is strcmp().
*/
static int
comp_string(const char *s1, const char *s2)
{
jint v1, v2;
if (isjavaint(s1, &v1) && isjavaint(s2, &v2))
return ((int)(v1 - v2));
else
return (JLI_StrCmp(s1, s2));
}
/*
* Modeled after strcmp(), compare two version-ids for a Prefix
* Match as defined in JSR 56.
*/
int
JLI_PrefixVersionId(const char *id1, char *id2)
{
char *s1 = JLI_StringDup(id1);
char *s2 = JLI_StringDup(id2);
char *m1 = s1;
char *m2 = s2;
char *end1 = NULL;
char *end2 = NULL;
int res = 0;
do {
if ((s1 != NULL) && ((end1 = JLI_StrPBrk(s1, ".-_")) != NULL))
*end1 = '\0';
if ((s2 != NULL) && ((end2 = JLI_StrPBrk(s2, ".-_")) != NULL))
*end2 = '\0';
res = comp_string(s1, s2);
if (end1 != NULL)
s1 = end1 + 1;
else
s1 = NULL;
if (end2 != NULL)
s2 = end2 + 1;
else
s2 = NULL;
} while (res == 0 && ((s1 != NULL) && (s2 != NULL)));
JLI_MemFree(m1);
JLI_MemFree(m2);
return (res);
}
/*
* Modeled after strcmp(), compare two version-ids for an Exact
* Match as defined in JSR 56.
*/
int
JLI_ExactVersionId(const char *id1, char *id2)
{
char *s1 = JLI_StringDup(id1);
char *s2 = JLI_StringDup(id2);
char *m1 = s1;
char *m2 = s2;
char *end1 = NULL;
char *end2 = NULL;
int res = 0;
do {
if ((s1 != NULL) && ((end1 = JLI_StrPBrk(s1, separators)) != NULL))
*end1 = '\0';
if ((s2 != NULL) && ((end2 = JLI_StrPBrk(s2, separators)) != NULL))
*end2 = '\0';
if ((s1 != NULL) && (s2 == NULL))
res = comp_string(s1, zero_string);
else if ((s1 == NULL) && (s2 != NULL))
res = comp_string(zero_string, s2);
else
res = comp_string(s1, s2);
if (end1 != NULL)
s1 = end1 + 1;
else
s1 = NULL;
if (end2 != NULL)
s2 = end2 + 1;
else
s2 = NULL;
} while (res == 0 && ((s1 != NULL) || (s2 != NULL)));
JLI_MemFree(m1);
JLI_MemFree(m2);
return (res);
}
/*
* Return true if this simple-element (as defined in JSR 56) forms
* an acceptable match.
*
* JSR 56 is modified by the Java Web Start <rel> Developer Guide
* where it is stated "... Java Web Start will not consider an installed
* non-FCS (i.e., milestone) JRE as a match. ... a JRE from Sun
* Microsystems, Inc., is by convention a non-FCS (milestone) JRE
* if there is a dash (-) in the version string."
*
* An undocumented caveat to the above is that an exact match with a
* hyphen is accepted as a development extension.
*
* These modifications are addressed by the specific comparisons
* for releases with hyphens.
*/
static int
acceptable_simple_element(const char *release, char *simple_element)
{
char *modifier;
modifier = simple_element + JLI_StrLen(simple_element) - 1;
if (*modifier == '*') {
*modifier = '\0';
if (JLI_StrChr(release, '-'))
return ((JLI_StrCmp(release, simple_element) == 0)?1:0);
return ((JLI_PrefixVersionId(release, simple_element) == 0)?1:0);
} else if (*modifier == '+') {
*modifier = '\0';
if (JLI_StrChr(release, '-'))
return ((JLI_StrCmp(release, simple_element) == 0)?1:0);
return ((JLI_ExactVersionId(release, simple_element) >= 0)?1:0);
} else {
return ((JLI_ExactVersionId(release, simple_element) == 0)?1:0);
}
}
/*
* Return true if this element (as defined in JSR 56) forms
* an acceptable match. An element is the intersection (and)
* of multiple simple-elements.
*/
static int
acceptable_element(const char *release, char *element)
{
char *end;
do {
if ((end = JLI_StrChr(element, '&')) != NULL)
*end = '\0';
if (!acceptable_simple_element(release, element))
return (0);
if (end != NULL)
element = end + 1;
} while (end != NULL);
return (1);
}
/*
* Checks if release is acceptable by the specification version-string.
* Return true if this version-string (as defined in JSR 56) forms
* an acceptable match. A version-string is the union (or) of multiple
* elements.
*/
int
JLI_AcceptableRelease(const char *release, char *version_string)
{
char *vs;
char *m1;
char *end;
m1 = vs = JLI_StringDup(version_string);
do {
if ((end = JLI_StrChr(vs, ' ')) != NULL)
*end = '\0';
if (acceptable_element(release, vs)) {
JLI_MemFree(m1);
return (1);
}
if (end != NULL)
vs = end + 1;
} while (end != NULL);
JLI_MemFree(m1);
return (0);
}
/*
* Return true if this is a valid simple-element (as defined in JSR 56).
*
* The official grammar for a simple-element is:
*
* simple-element ::= version-id | version-id modifier
* modifier ::= '+' | '*'
* version-id ::= string ( separator string )*
* string ::= char ( char )*
* char ::= Any ASCII character except a space, an
* ampersand, a separator or a modifier
* separator ::= '.' | '-' | '_'
*
* However, for efficiency, it is time to abandon the top down parser
* implementation. After deleting the potential trailing modifier, we
* are left with a version-id.
*
* Note that a valid version-id has three simple properties:
*
* 1) Doesn't contain a space, an ampersand or a modifier.
*
* 2) Doesn't begin or end with a separator.
*
* 3) Doesn't contain two adjacent separators.
*
* Any other line noise constitutes a valid version-id.
*/
static int
valid_simple_element(char *simple_element)
{
char *last;
size_t len;
if ((simple_element == NULL) || ((len = JLI_StrLen(simple_element)) == 0))
return (0);
last = simple_element + len - 1;
if (*last == '*' || *last == '+') {
if (--len == 0)
return (0);
*last-- = '\0';
}
if (JLI_StrPBrk(simple_element, " &+*") != NULL) /* Property #1 */
return (0);
if ((JLI_StrChr(".-_", *simple_element) != NULL) || /* Property #2 */
(JLI_StrChr(".-_", *last) != NULL))
return (0);
for (; simple_element != last; simple_element++) /* Property #3 */
if ((JLI_StrChr(".-_", *simple_element) != NULL) &&
(JLI_StrChr(".-_", *(simple_element + 1)) != NULL))
return (0);
return (1);
}
/*
* Return true if this is a valid element (as defined in JSR 56).
* An element is the intersection (and) of multiple simple-elements.
*/
static int
valid_element(char *element)
{
char *end;
if ((element == NULL) || (JLI_StrLen(element) == 0))
return (0);
do {
if ((end = JLI_StrChr(element, '&')) != NULL)
*end = '\0';
if (!valid_simple_element(element))
return (0);
if (end != NULL)
element = end + 1;
} while (end != NULL);
return (1);
}
/*
* Validates a version string by the extended JSR 56 grammar.
*/
int
JLI_ValidVersionString(char *version_string)
{
char *vs;
char *m1;
char *end;
if ((version_string == NULL) || (JLI_StrLen(version_string) == 0))
return (0);
m1 = vs = JLI_StringDup(version_string);
do {
if ((end = JLI_StrChr(vs, ' ')) != NULL)
*end = '\0';
if (!valid_element(vs)) {
JLI_MemFree(m1);
return (0);
}
if (end != NULL)
vs = end + 1;
} while (end != NULL);
JLI_MemFree(m1);
return (1);
}

@ -0,0 +1,37 @@
/*
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
#ifndef _VERSION_COMP_H
#define _VERSION_COMP_H
/*
* Function prototypes.
*/
int JLI_ExactVersionId(const char *id1, char *id2);
int JLI_PrefixVersionId(const char *id1, char *id2);
int JLI_AcceptableRelease(const char *release, char *version_string);
int JLI_ValidVersionString(char *version_string);
#endif /* _VERSION_COMP_H */

@ -0,0 +1,501 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
/*
* Class-Path Wildcards
*
* The syntax for wildcards is a single asterisk. The class path
* foo/"*", e.g., loads all jar files in the directory named foo.
* (This requires careful quotation when used in shell scripts.)
*
* Only files whose names end in .jar or .JAR are matched.
* Files whose names end in .zip, or which have a particular
* magic number, regardless of filename extension, are not
* matched.
*
* Files are considered regardless of whether or not they are
* "hidden" in the UNIX sense, i.e., have names beginning with '.'.
*
* A wildcard only matches jar files, not class files in the same
* directory. If you want to load both class files and jar files from
* a single directory foo then you can say foo:foo/"*", or foo/"*":foo
* if you want the jar files to take precedence.
*
* Subdirectories are not searched recursively, i.e., foo/"*" only
* looks for jar files in foo, not in foo/bar, foo/baz, etc.
*
* Expansion of wildcards is done early, prior to the invocation of a
* program's main method, rather than late, during the class-loading
* process itself. Each element of the input class path containing a
* wildcard is replaced by the (possibly empty) sequence of elements
* generated by enumerating the jar files in the named directory. If
* the directory foo contains a.jar, b.jar, and c.jar,
* e.g., then the class path foo/"*" is expanded into
* foo/a.jar:foo/b.jar:foo/c.jar, and that string would be the value
* of the system property java.class.path.
*
* The order in which the jar files in a directory are enumerated in
* the expanded class path is not specified and may vary from platform
* to platform and even from moment to moment on the same machine. A
* well-constructed application should not depend upon any particular
* order. If a specific order is required then the jar files can be
* enumerated explicitly in the class path.
*
* The CLASSPATH environment variable is not treated any differently
* from the -classpath (equiv. -cp) command-line option,
* i.e. wildcards are honored in all these cases.
*
* Class-path wildcards are not honored in the Class-Path jar-manifest
* header.
*
* Class-path wildcards are honored not only by the Java launcher but
* also by most other command-line tools that accept class paths, and
* in particular by javac and javadoc.
*
* Class-path wildcards are not honored in any other kind of path, and
* especially not in the bootstrap class path, which is a mere
* artifact of our implementation and not something that developers
* should use.
*
* Classpath wildcards are only expanded in the Java launcher code,
* supporting the use of wildcards on the command line and in the
* CLASSPATH environment variable. We do not support the use of
* wildcards by applications that embed the JVM.
*/
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include "java.h" /* Strictly for PATH_SEPARATOR/FILE_SEPARATOR */
#include "jli_util.h"
#ifdef _WIN32
#include <windows.h>
#else /* Unix */
#include <unistd.h>
#include <dirent.h>
#endif /* Unix */
static int
exists(const char* filename)
{
#ifdef _WIN32
return _access(filename, 0) == 0;
#else
return access(filename, F_OK) == 0;
#endif
}
#define NEW_(TYPE) ((TYPE) JLI_MemAlloc(sizeof(struct TYPE##_)))
/*
* Wildcard directory iteration.
* WildcardIterator_for(wildcard) returns an iterator.
* Each call to that iterator's next() method returns the basename
* of an entry in the wildcard's directory. The basename's memory
* belongs to the iterator. The caller is responsible for prepending
* the directory name and file separator, if necessary.
* When done with the iterator, call the close method to clean up.
*/
typedef struct WildcardIterator_* WildcardIterator;
#ifdef _WIN32
struct WildcardIterator_
{
HANDLE handle;
char *firstFile; /* Stupid FindFirstFile...FindNextFile */
};
// since this is used repeatedly we keep it here.
static WIN32_FIND_DATA find_data;
static WildcardIterator
WildcardIterator_for(const char *wildcard)
{
WildcardIterator it = NEW_(WildcardIterator);
HANDLE handle = FindFirstFile(wildcard, &find_data);
if (handle == INVALID_HANDLE_VALUE) {
JLI_MemFree(it);
return NULL;
}
it->handle = handle;
it->firstFile = find_data.cFileName;
return it;
}
static char *
WildcardIterator_next(WildcardIterator it)
{
if (it->firstFile != NULL) {
char *firstFile = it->firstFile;
it->firstFile = NULL;
return firstFile;
}
return FindNextFile(it->handle, &find_data)
? find_data.cFileName : NULL;
}
static void
WildcardIterator_close(WildcardIterator it)
{
if (it) {
FindClose(it->handle);
JLI_MemFree(it->firstFile);
JLI_MemFree(it);
}
}
#else /* Unix */
struct WildcardIterator_
{
DIR *dir;
};
static WildcardIterator
WildcardIterator_for(const char *wildcard)
{
DIR *dir;
int wildlen = JLI_StrLen(wildcard);
if (wildlen < 2) {
dir = opendir(".");
} else {
char *dirname = JLI_StringDup(wildcard);
dirname[wildlen - 1] = '\0';
dir = opendir(dirname);
JLI_MemFree(dirname);
}
if (dir == NULL)
return NULL;
else {
WildcardIterator it = NEW_(WildcardIterator);
it->dir = dir;
return it;
}
}
static char *
WildcardIterator_next(WildcardIterator it)
{
struct dirent* dirp = readdir(it->dir);
return dirp ? dirp->d_name : NULL;
}
static void
WildcardIterator_close(WildcardIterator it)
{
if (it) {
closedir(it->dir);
JLI_MemFree(it);
}
}
#endif /* Unix */
static int
equal(const char *s1, const char *s2)
{
return JLI_StrCmp(s1, s2) == 0;
}
/*
* FileList ADT - a dynamic list of C filenames
*/
struct FileList_
{
char **files;
int size;
int capacity;
};
typedef struct FileList_ *FileList;
static FileList
FileList_new(int capacity)
{
FileList fl = NEW_(FileList);
fl->capacity = capacity;
fl->files = (char **) JLI_MemAlloc(capacity * sizeof(fl->files[0]));
fl->size = 0;
return fl;
}
static void
FileList_free(FileList fl)
{
if (fl) {
if (fl->files) {
int i;
for (i = 0; i < fl->size; i++)
JLI_MemFree(fl->files[i]);
JLI_MemFree(fl->files);
}
JLI_MemFree(fl);
}
}
static void
FileList_ensureCapacity(FileList fl, int capacity)
{
if (fl->capacity < capacity) {
while (fl->capacity < capacity)
fl->capacity *= 2;
fl->files = JLI_MemRealloc(fl->files,
fl->capacity * sizeof(fl->files[0]));
}
}
static void
FileList_add(FileList fl, char *file)
{
FileList_ensureCapacity(fl, fl->size+1);
fl->files[fl->size++] = file;
}
static void
FileList_addSubstring(FileList fl, const char *beg, int len)
{
char *filename = (char *) JLI_MemAlloc(len+1);
memcpy(filename, beg, len);
filename[len] = '\0';
FileList_ensureCapacity(fl, fl->size+1);
fl->files[fl->size++] = filename;
}
static char *
FileList_join(FileList fl, char sep)
{
int i;
int size;
char *path;
char *p;
for (i = 0, size = 1; i < fl->size; i++)
size += (int)JLI_StrLen(fl->files[i]) + 1;
path = JLI_MemAlloc(size);
for (i = 0, p = path; i < fl->size; i++) {
int len = (int)JLI_StrLen(fl->files[i]);
if (i > 0) *p++ = sep;
memcpy(p, fl->files[i], len);
p += len;
}
*p = '\0';
return path;
}
static FileList
FileList_split(const char *path, char sep)
{
const char *p, *q;
int len = (int)JLI_StrLen(path);
int count;
FileList fl;
for (count = 1, p = path; p < path + len; p++)
count += (*p == sep);
fl = FileList_new(count);
for (p = path;;) {
for (q = p; q <= path + len; q++) {
if (*q == sep || *q == '\0') {
FileList_addSubstring(fl, p, q - p);
if (*q == '\0')
return fl;
p = q + 1;
}
}
}
}
static int
isJarFileName(const char *filename)
{
int len = (int)JLI_StrLen(filename);
return (len >= 4) &&
(filename[len - 4] == '.') &&
(equal(filename + len - 3, "jar") ||
equal(filename + len - 3, "JAR")) &&
/* Paranoia: Maybe filename is "DIR:foo.jar" */
(JLI_StrChr(filename, PATH_SEPARATOR) == NULL);
}
static char *
wildcardConcat(const char *wildcard, const char *basename)
{
int wildlen = (int)JLI_StrLen(wildcard);
int baselen = (int)JLI_StrLen(basename);
char *filename = (char *) JLI_MemAlloc(wildlen + baselen);
/* Replace the trailing '*' with basename */
memcpy(filename, wildcard, wildlen-1);
memcpy(filename+wildlen-1, basename, baselen+1);
return filename;
}
static FileList
wildcardFileList(const char *wildcard)
{
const char *basename;
FileList fl = FileList_new(16);
WildcardIterator it = WildcardIterator_for(wildcard);
if (it == NULL)
{
FileList_free(fl);
return NULL;
}
while ((basename = WildcardIterator_next(it)) != NULL)
if (isJarFileName(basename))
FileList_add(fl, wildcardConcat(wildcard, basename));
WildcardIterator_close(it);
return fl;
}
static int
isWildcard(const char *filename)
{
int len = (int)JLI_StrLen(filename);
return (len > 0) &&
(filename[len - 1] == '*') &&
(len == 1 || IS_FILE_SEPARATOR(filename[len - 2])) &&
(! exists(filename));
}
static void
FileList_expandWildcards(FileList fl)
{
int i, j;
for (i = 0; i < fl->size; i++) {
if (isWildcard(fl->files[i])) {
FileList expanded = wildcardFileList(fl->files[i]);
if (expanded != NULL && expanded->size > 0) {
JLI_MemFree(fl->files[i]);
FileList_ensureCapacity(fl, fl->size + expanded->size);
for (j = fl->size - 1; j >= i+1; j--)
fl->files[j+expanded->size-1] = fl->files[j];
for (j = 0; j < expanded->size; j++)
fl->files[i+j] = expanded->files[j];
i += expanded->size - 1;
fl->size += expanded->size - 1;
/* fl expropriates expanded's elements. */
expanded->size = 0;
}
FileList_free(expanded);
}
}
}
const char *
JLI_WildcardExpandClasspath(const char *classpath)
{
char *expanded;
FileList fl;
if (JLI_StrChr(classpath, '*') == NULL)
return classpath;
fl = FileList_split(classpath, PATH_SEPARATOR);
FileList_expandWildcards(fl);
expanded = FileList_join(fl, PATH_SEPARATOR);
FileList_free(fl);
if (getenv(JLDEBUG_ENV_ENTRY) != 0)
printf("Expanded wildcards:\n"
" before: \"%s\"\n"
" after : \"%s\"\n",
classpath, expanded);
return expanded;
}
#ifdef DEBUG_WILDCARD
static void
FileList_print(FileList fl)
{
int i;
putchar('[');
for (i = 0; i < fl->size; i++) {
if (i > 0) printf(", ");
printf("\"%s\"",fl->files[i]);
}
putchar(']');
}
static void
wildcardExpandArgv(const char ***argv)
{
int i;
for (i = 0; (*argv)[i]; i++) {
if (equal((*argv)[i], "-cp") ||
equal((*argv)[i], "-classpath")) {
i++;
(*argv)[i] = wildcardExpandClasspath((*argv)[i]);
}
}
}
static void
debugPrintArgv(char *argv[])
{
int i;
putchar('[');
for (i = 0; argv[i]; i++) {
if (i > 0) printf(", ");
printf("\"%s\"", argv[i]);
}
printf("]\n");
}
int
main(int argc, char *argv[])
{
argv[0] = "java";
wildcardExpandArgv((const char***)&argv);
debugPrintArgv(argv);
/* execvp("java", argv); */
return 0;
}
#endif /* DEBUG_WILDCARD */
/* Cute little perl prototype implementation....
my $sep = ($^O =~ /^(Windows|cygwin)/) ? ";" : ":";
sub expand($) {
opendir DIR, $_[0] or return $_[0];
join $sep, map {"$_[0]/$_"} grep {/\.(jar|JAR)$/} readdir DIR;
}
sub munge($) {
join $sep,
map {(! -r $_ and s/[\/\\]+\*$//) ? expand $_ : $_} split $sep, $_[0];
}
for (my $i = 0; $i < @ARGV - 1; $i++) {
$ARGV[$i+1] = munge $ARGV[$i+1] if $ARGV[$i] =~ /^-c(p|lasspath)$/;
}
$ENV{CLASSPATH} = munge $ENV{CLASSPATH} if exists $ENV{CLASSPATH};
@ARGV = ("java", @ARGV);
print "@ARGV\n";
exec @ARGV;
*/

@ -0,0 +1,31 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
#ifndef WILDCARD_H_
#define WILDCARD_H_
const char *JLI_WildcardExpandClasspath(const char *classpath);
#endif /* include guard */

@ -0,0 +1,4 @@
3 5 0 8 4 2 1 7 3 6 1 2 3 4 5 6 7 8 0
3 6 4 7 8 5 0 3 2 1 1 2 3 4 5 6 7 8 0
3 8 6 7 2 5 4 3 0 1 1 2 3 4 5 6 7 8 0
4 8 13 0 6 1 15 9 14 3 4 5 11 7 2 10 12 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: runner.SearchRunner

@ -0,0 +1,819 @@
package algs4.util;
/******************************************************************************
* Compilation: javac In.java
* Execution: java In (basic test --- see source for required files)
* Dependencies: none
*
* Reads in data of various types from standard input, files, and URLs.
*
******************************************************************************/
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.Socket;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.InputMismatchException;
import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.regex.Pattern;
/**
* <i>Input</i>. This class provides methods for reading strings
* and numbers from standard input, file input, URLs, and sockets.
* <p>
* The Locale used is: language = English, country = US. This is consistent
* with the formatting conventions with Java floating-point literals,
* command-line arguments (via {@link Double#parseDouble(String)})
* and standard output.
* <p>
* For additional documentation, see
* <a href="https://introcs.cs.princeton.edu/31datatype">Section 3.1</a> of
* <i>Computer Science: An Interdisciplinary Approach</i>
* by Robert Sedgewick and Kevin Wayne.
* <p>
* Like {@link Scanner}, reading a token also consumes preceding Java
* whitespace, reading a full line consumes
* the following end-of-line delimeter, while reading a character consumes
* nothing extra.
* <p>
* Whitespace is defined in {@link Character#isWhitespace(char)}. Newlines
* consist of \n, \r, \r\n, and Unicode hex code points 0x2028, 0x2029, 0x0085;
* see <a href="http://www.docjar.com/html/api/java/util/Scanner.java.html">
* Scanner.java</a> (NB: Java 6u23 and earlier uses only \r, \r, \r\n).
*
* @author David Pritchard
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public final class In {
///// begin: section (1 of 2) of code duplicated from In to StdIn.
// assume Unicode UTF-8 encoding
private static final String CHARSET_NAME = "UTF-8";
// assume language = English, country = US for consistency with System.out.
private static final Locale LOCALE = Locale.US;
// the default token separator; we maintain the invariant that this value
// is held by the scanner's delimiter between calls
private static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\p{javaWhitespace}+");
// makes whitespace characters significant
private static final Pattern EMPTY_PATTERN = Pattern.compile("");
// used to read the entire input. source:
// http://weblogs.java.net/blog/pat/archive/2004/10/stupid_scanner_1.html
private static final Pattern EVERYTHING_PATTERN = Pattern.compile("\\A");
//// end: section (1 of 2) of code duplicated from In to StdIn.
private Scanner scanner;
/**
* Initializes an input stream from standard input.
*/
public In() {
scanner = new Scanner(new BufferedInputStream(System.in), CHARSET_NAME);
scanner.useLocale(LOCALE);
}
/**
* Initializes an input stream from a socket.
*
* @param socket the socket
* @throws IllegalArgumentException if cannot open {@code socket}
* @throws IllegalArgumentException if {@code socket} is {@code null}
*/
public In(Socket socket) {
if (socket == null) throw new IllegalArgumentException("socket argument is null");
try {
InputStream is = socket.getInputStream();
scanner = new Scanner(new BufferedInputStream(is), CHARSET_NAME);
scanner.useLocale(LOCALE);
}
catch (IOException ioe) {
throw new IllegalArgumentException("Could not open " + socket, ioe);
}
}
/**
* Initializes an input stream from a URL.
*
* @param url the URL
* @throws IllegalArgumentException if cannot open {@code url}
* @throws IllegalArgumentException if {@code url} is {@code null}
*/
public In(URL url) {
if (url == null) throw new IllegalArgumentException("url argument is null");
try {
URLConnection site = url.openConnection();
InputStream is = site.getInputStream();
scanner = new Scanner(new BufferedInputStream(is), CHARSET_NAME);
scanner.useLocale(LOCALE);
}
catch (IOException ioe) {
throw new IllegalArgumentException("Could not open " + url, ioe);
}
}
/**
* Initializes an input stream from a file.
*
* @param file the file
* @throws IllegalArgumentException if cannot open {@code file}
* @throws IllegalArgumentException if {@code file} is {@code null}
*/
public In(File file) {
if (file == null) throw new IllegalArgumentException("file argument is null");
try {
// for consistency with StdIn, wrap with BufferedInputStream instead of use
// file as argument to Scanner
FileInputStream fis = new FileInputStream(file);
scanner = new Scanner(new BufferedInputStream(fis), CHARSET_NAME);
scanner.useLocale(LOCALE);
}
catch (IOException ioe) {
throw new IllegalArgumentException("Could not open " + file, ioe);
}
}
/**
* Initializes an input stream from a filename or web page name.
*
* @param name the filename or web page name
* @throws IllegalArgumentException if cannot open {@code name} as
* a file or URL
* @throws IllegalArgumentException if {@code name} is {@code null}
*/
public In(String name) {
if (name == null) throw new IllegalArgumentException("argument is null");
if (name.length() == 0) throw new IllegalArgumentException("argument is the empty string");
try {
// first try to read file from local file system
File file = new File(name);
if (file.exists()) {
// for consistency with StdIn, wrap with BufferedInputStream instead of use
// file as argument to Scanner
FileInputStream fis = new FileInputStream(file);
scanner = new Scanner(new BufferedInputStream(fis), CHARSET_NAME);
scanner.useLocale(LOCALE);
return;
}
// resource relative to .class file
URL url = getClass().getResource(name);
// resource relative to classloader root
if (url == null) {
url = getClass().getClassLoader().getResource(name);
}
// or URL from web
if (url == null) {
url = new URL(name);
}
URLConnection site = url.openConnection();
// in order to set User-Agent, replace above line with these two
// HttpURLConnection site = (HttpURLConnection) url.openConnection();
// site.addRequestProperty("User-Agent", "Mozilla/4.76");
InputStream is = site.getInputStream();
scanner = new Scanner(new BufferedInputStream(is), CHARSET_NAME);
scanner.useLocale(LOCALE);
}
catch (IOException ioe) {
throw new IllegalArgumentException("Could not open " + name, ioe);
}
}
/**
* Initializes an input stream from a given {@link Scanner} source; use with
* {@code new Scanner(String)} to read from a string.
* <p>
* Note that this does not create a defensive copy, so the
* scanner will be mutated as you read on.
*
* @param scanner the scanner
* @throws IllegalArgumentException if {@code scanner} is {@code null}
*/
public In(Scanner scanner) {
if (scanner == null) throw new IllegalArgumentException("scanner argument is null");
this.scanner = scanner;
}
/**
* Returns true if this input stream exists.
*
* @return {@code true} if this input stream exists; {@code false} otherwise
*/
public boolean exists() {
return scanner != null;
}
//// begin: section (2 of 2) of code duplicated from In to StdIn,
//// with all methods changed from "public" to "public static".
/**
* Returns true if input stream is empty (except possibly whitespace).
* Use this to know whether the next call to {@link #readString()},
* {@link #readDouble()}, etc will succeed.
*
* @return {@code true} if this input stream is empty (except possibly whitespace);
* {@code false} otherwise
*/
public boolean isEmpty() {
return !scanner.hasNext();
}
/**
* Returns true if this input stream has a next line.
* Use this method to know whether the
* next call to {@link #readLine()} will succeed.
* This method is functionally equivalent to {@link #hasNextChar()}.
*
* @return {@code true} if this input stream has more input (including whitespace);
* {@code false} otherwise
*/
public boolean hasNextLine() {
return scanner.hasNextLine();
}
/**
* Returns true if this input stream has more input (including whitespace).
* Use this method to know whether the next call to {@link #readChar()} will succeed.
* This method is functionally equivalent to {@link #hasNextLine()}.
*
* @return {@code true} if this input stream has more input (including whitespace);
* {@code false} otherwise
*/
public boolean hasNextChar() {
scanner.useDelimiter(EMPTY_PATTERN);
boolean result = scanner.hasNext();
scanner.useDelimiter(WHITESPACE_PATTERN);
return result;
}
/**
* Reads and returns the next line in this input stream.
*
* @return the next line in this input stream; {@code null} if no such line
*/
public String readLine() {
String line;
try {
line = scanner.nextLine();
}
catch (NoSuchElementException e) {
line = null;
}
return line;
}
/**
* Reads and returns the next character in this input stream.
*
* @return the next {@code char} in this input stream
* @throws NoSuchElementException if the input stream is empty
*/
public char readChar() {
scanner.useDelimiter(EMPTY_PATTERN);
try {
String ch = scanner.next();
assert ch.length() == 1 : "Internal (Std)In.readChar() error!"
+ " Please contact the authors.";
scanner.useDelimiter(WHITESPACE_PATTERN);
return ch.charAt(0);
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'char' value from the input stream, "
+ "but no more tokens are available");
}
}
/**
* Reads and returns the remainder of this input stream, as a string.
*
* @return the remainder of this input stream, as a string
*/
public String readAll() {
if (!scanner.hasNextLine())
return "";
String result = scanner.useDelimiter(EVERYTHING_PATTERN).next();
// not that important to reset delimeter, since now scanner is empty
scanner.useDelimiter(WHITESPACE_PATTERN); // but let's do it anyway
return result;
}
/**
* Reads the next token from this input stream and returns it as a {@code String}.
*
* @return the next {@code String} in this input stream
* @throws NoSuchElementException if the input stream is empty
*/
public String readString() {
try {
return scanner.next();
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'String' value from the input stream, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from this input stream, parses it as a {@code int},
* and returns the {@code int}.
*
* @return the next {@code int} in this input stream
* @throws NoSuchElementException if the input stream is empty
* @throws InputMismatchException if the next token cannot be parsed as an {@code int}
*/
public int readInt() {
try {
return scanner.nextInt();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read an 'int' value from the input stream, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attemps to read an 'int' value from the input stream, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from this input stream, parses it as a {@code double},
* and returns the {@code double}.
*
* @return the next {@code double} in this input stream
* @throws NoSuchElementException if the input stream is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code double}
*/
public double readDouble() {
try {
return scanner.nextDouble();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read a 'double' value from the input stream, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attemps to read a 'double' value from the input stream, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from this input stream, parses it as a {@code float},
* and returns the {@code float}.
*
* @return the next {@code float} in this input stream
* @throws NoSuchElementException if the input stream is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code float}
*/
public float readFloat() {
try {
return scanner.nextFloat();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read a 'float' value from the input stream, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attemps to read a 'float' value from the input stream, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from this input stream, parses it as a {@code long},
* and returns the {@code long}.
*
* @return the next {@code long} in this input stream
* @throws NoSuchElementException if the input stream is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code long}
*/
public long readLong() {
try {
return scanner.nextLong();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read a 'long' value from the input stream, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attemps to read a 'long' value from the input stream, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from this input stream, parses it as a {@code short},
* and returns the {@code short}.
*
* @return the next {@code short} in this input stream
* @throws NoSuchElementException if the input stream is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code short}
*/
public short readShort() {
try {
return scanner.nextShort();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read a 'short' value from the input stream, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attemps to read a 'short' value from the input stream, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from this input stream, parses it as a {@code byte},
* and returns the {@code byte}.
* <p>
* To read binary data, use {@link BinaryIn}.
*
* @return the next {@code byte} in this input stream
* @throws NoSuchElementException if the input stream is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code byte}
*/
public byte readByte() {
try {
return scanner.nextByte();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read a 'byte' value from the input stream, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attemps to read a 'byte' value from the input stream, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from this input stream, parses it as a {@code boolean}
* (interpreting either {@code "true"} or {@code "1"} as {@code true},
* and either {@code "false"} or {@code "0"} as {@code false}).
*
* @return the next {@code boolean} in this input stream
* @throws NoSuchElementException if the input stream is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code boolean}
*/
public boolean readBoolean() {
try {
String token = readString();
if ("true".equalsIgnoreCase(token)) return true;
if ("false".equalsIgnoreCase(token)) return false;
if ("1".equals(token)) return true;
if ("0".equals(token)) return false;
throw new InputMismatchException("attempts to read a 'boolean' value from the input stream, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'boolean' value from the input stream, "
+ "but no more tokens are available");
}
}
/**
* Reads all remaining tokens from this input stream and returns them as
* an array of strings.
*
* @return all remaining tokens in this input stream, as an array of strings
*/
public String[] readAllStrings() {
// we could use readAll.trim().split(), but that's not consistent
// since trim() uses characters 0x00..0x20 as whitespace
String[] tokens = WHITESPACE_PATTERN.split(readAll());
if (tokens.length == 0 || tokens[0].length() > 0)
return tokens;
String[] decapitokens = new String[tokens.length-1];
for (int i = 0; i < tokens.length-1; i++)
decapitokens[i] = tokens[i+1];
return decapitokens;
}
/**
* Reads all remaining lines from this input stream and returns them as
* an array of strings.
*
* @return all remaining lines in this input stream, as an array of strings
*/
public String[] readAllLines() {
ArrayList<String> lines = new ArrayList<String>();
while (hasNextLine()) {
lines.add(readLine());
}
return lines.toArray(new String[lines.size()]);
}
/**
* Reads all remaining tokens from this input stream, parses them as integers,
* and returns them as an array of integers.
*
* @return all remaining lines in this input stream, as an array of integers
*/
public int[] readAllInts() {
String[] fields = readAllStrings();
int[] vals = new int[fields.length];
for (int i = 0; i < fields.length; i++)
vals[i] = Integer.parseInt(fields[i]);
return vals;
}
/**
* Reads all remaining tokens from this input stream, parses them as longs,
* and returns them as an array of longs.
*
* @return all remaining lines in this input stream, as an array of longs
*/
public long[] readAllLongs() {
String[] fields = readAllStrings();
long[] vals = new long[fields.length];
for (int i = 0; i < fields.length; i++)
vals[i] = Long.parseLong(fields[i]);
return vals;
}
/**
* Reads all remaining tokens from this input stream, parses them as doubles,
* and returns them as an array of doubles.
*
* @return all remaining lines in this input stream, as an array of doubles
*/
public double[] readAllDoubles() {
String[] fields = readAllStrings();
double[] vals = new double[fields.length];
for (int i = 0; i < fields.length; i++)
vals[i] = Double.parseDouble(fields[i]);
return vals;
}
///// end: section (2 of 2) of code duplicated from In to StdIn */
/**
* Closes this input stream.
*/
public void close() {
scanner.close();
}
/**
* Reads all integers from a file and returns them as
* an array of integers.
*
* @param filename the name of the file
* @return the integers in the file
* @deprecated Replaced by {@code new In(filename)}.{@link #readAllInts()}.
*/
@Deprecated
public static int[] readInts(String filename) {
return new In(filename).readAllInts();
}
/**
* Reads all doubles from a file and returns them as
* an array of doubles.
*
* @param filename the name of the file
* @return the doubles in the file
* @deprecated Replaced by {@code new In(filename)}.{@link #readAllDoubles()}.
*/
@Deprecated
public static double[] readDoubles(String filename) {
return new In(filename).readAllDoubles();
}
/**
* Reads all strings from a file and returns them as
* an array of strings.
*
* @param filename the name of the file
* @return the strings in the file
* @deprecated Replaced by {@code new In(filename)}.{@link #readAllStrings()}.
*/
@Deprecated
public static String[] readStrings(String filename) {
return new In(filename).readAllStrings();
}
/**
* Reads all integers from standard input and returns them
* an array of integers.
*
* @return the integers on standard input
* @deprecated Replaced by {@link StdIn#readAllInts()}.
*/
@Deprecated
public static int[] readInts() {
return new In().readAllInts();
}
/**
* Reads all doubles from standard input and returns them as
* an array of doubles.
*
* @return the doubles on standard input
* @deprecated Replaced by {@link StdIn#readAllDoubles()}.
*/
@Deprecated
public static double[] readDoubles() {
return new In().readAllDoubles();
}
/**
* Reads all strings from standard input and returns them as
* an array of strings.
*
* @return the strings on standard input
* @deprecated Replaced by {@link StdIn#readAllStrings()}.
*/
@Deprecated
public static String[] readStrings() {
return new In().readAllStrings();
}
/**
* Unit tests the {@code In} data type.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
In in;
String urlName = "https://introcs.cs.princeton.edu/java/stdlib/InTest.txt";
// read from a URL
System.out.println("readAll() from URL " + urlName);
System.out.println("---------------------------------------------------------------------------");
try {
in = new In(urlName);
System.out.println(in.readAll());
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
// read one line at a time from URL
System.out.println("readLine() from URL " + urlName);
System.out.println("---------------------------------------------------------------------------");
try {
in = new In(urlName);
while (!in.isEmpty()) {
String s = in.readLine();
System.out.println(s);
}
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
// read one string at a time from URL
System.out.println("readString() from URL " + urlName);
System.out.println("---------------------------------------------------------------------------");
try {
in = new In(urlName);
while (!in.isEmpty()) {
String s = in.readString();
System.out.println(s);
}
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
// read one line at a time from file in current directory
System.out.println("readLine() from current directory");
System.out.println("---------------------------------------------------------------------------");
try {
in = new In("./InTest.txt");
while (!in.isEmpty()) {
String s = in.readLine();
System.out.println(s);
}
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
// read one line at a time from file using relative path
System.out.println("readLine() from relative path");
System.out.println("---------------------------------------------------------------------------");
try {
in = new In("../stdlib/InTest.txt");
while (!in.isEmpty()) {
String s = in.readLine();
System.out.println(s);
}
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
// read one char at a time
System.out.println("readChar() from file");
System.out.println("---------------------------------------------------------------------------");
try {
in = new In("InTest.txt");
while (!in.isEmpty()) {
char c = in.readChar();
System.out.print(c);
}
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
System.out.println();
// read one line at a time from absolute OS X / Linux path
System.out.println("readLine() from absolute OS X / Linux path");
System.out.println("---------------------------------------------------------------------------");
try {
in = new In("/n/fs/introcs/www/java/stdlib/InTest.txt");
while (!in.isEmpty()) {
String s = in.readLine();
System.out.println(s);
}
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
// read one line at a time from absolute Windows path
System.out.println("readLine() from absolute Windows path");
System.out.println("---------------------------------------------------------------------------");
try {
in = new In("G:\\www\\introcs\\stdlib\\InTest.txt");
while (!in.isEmpty()) {
String s = in.readLine();
System.out.println(s);
}
System.out.println();
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/

@ -0,0 +1,341 @@
package algs4.util;
/******************************************************************************
* Compilation: javac Out.java
* Execution: java Out
* Dependencies: none
*
* Writes data of various types to: stdout, file, or socket.
*
******************************************************************************/
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Locale;
/**
* This class provides methods for writing strings and numbers to
* various output streams, including standard output, file, and sockets.
* <p>
* For additional documentation, see
* <a href="https://introcs.cs.princeton.edu/31datatype">Section 3.1</a> of
* <i>Computer Science: An Interdisciplinary Approach</i>
* by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class Out {
// force Unicode UTF-8 encoding; otherwise it's system dependent
private static final String CHARSET_NAME = "UTF-8";
// assume language = English, country = US for consistency with In
private static final Locale LOCALE = Locale.US;
private PrintWriter out;
/**
* Initializes an output stream from a {@link OutputStream}.
*
* @param os the {@code OutputStream}
*/
public Out(OutputStream os) {
try {
OutputStreamWriter osw = new OutputStreamWriter(os, CHARSET_NAME);
out = new PrintWriter(osw, true);
}
catch (IOException e) {
e.printStackTrace();
}
}
/**
* Initializes an output stream from standard output.
*/
public Out() {
this(System.out);
}
/**
* Initializes an output stream from a socket.
*
* @param socket the socket
*/
public Out(Socket socket) {
try {
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os, CHARSET_NAME);
out = new PrintWriter(osw, true);
}
catch (IOException e) {
e.printStackTrace();
}
}
/**
* Initializes an output stream from a file.
*
* @param filename the name of the file
*/
public Out(String filename) {
try {
OutputStream os = new FileOutputStream(filename);
OutputStreamWriter osw = new OutputStreamWriter(os, CHARSET_NAME);
out = new PrintWriter(osw, true);
}
catch (IOException e) {
e.printStackTrace();
}
}
/**
* Closes the output stream.
*/
public void close() {
out.close();
}
/**
* Terminates the current line by printing the line-separator string.
*/
public void println() {
out.println();
}
/**
* Prints an object to this output stream and then terminates the line.
*
* @param x the object to print
*/
public void println(Object x) {
out.println(x);
}
/**
* Prints a boolean to this output stream and then terminates the line.
*
* @param x the boolean to print
*/
public void println(boolean x) {
out.println(x);
}
/**
* Prints a character to this output stream and then terminates the line.
*
* @param x the character to print
*/
public void println(char x) {
out.println(x);
}
/**
* Prints a double to this output stream and then terminates the line.
*
* @param x the double to print
*/
public void println(double x) {
out.println(x);
}
/**
* Prints a float to this output stream and then terminates the line.
*
* @param x the float to print
*/
public void println(float x) {
out.println(x);
}
/**
* Prints an integer to this output stream and then terminates the line.
*
* @param x the integer to print
*/
public void println(int x) {
out.println(x);
}
/**
* Prints a long to this output stream and then terminates the line.
*
* @param x the long to print
*/
public void println(long x) {
out.println(x);
}
/**
* Prints a byte to this output stream and then terminates the line.
* <p>
* To write binary data, see {@link BinaryOut}.
*
* @param x the byte to print
*/
public void println(byte x) {
out.println(x);
}
/**
* Flushes this output stream.
*/
public void print() {
out.flush();
}
/**
* Prints an object to this output stream and flushes this output stream.
*
* @param x the object to print
*/
public void print(Object x) {
out.print(x);
out.flush();
}
/**
* Prints a boolean to this output stream and flushes this output stream.
*
* @param x the boolean to print
*/
public void print(boolean x) {
out.print(x);
out.flush();
}
/**
* Prints a character to this output stream and flushes this output stream.
*
* @param x the character to print
*/
public void print(char x) {
out.print(x);
out.flush();
}
/**
* Prints a double to this output stream and flushes this output stream.
*
* @param x the double to print
*/
public void print(double x) {
out.print(x);
out.flush();
}
/**
* Prints a float to this output stream and flushes this output stream.
*
* @param x the float to print
*/
public void print(float x) {
out.print(x);
out.flush();
}
/**
* Prints an integer to this output stream and flushes this output stream.
*
* @param x the integer to print
*/
public void print(int x) {
out.print(x);
out.flush();
}
/**
* Prints a long integer to this output stream and flushes this output stream.
*
* @param x the long integer to print
*/
public void print(long x) {
out.print(x);
out.flush();
}
/**
* Prints a byte to this output stream and flushes this output stream.
*
* @param x the byte to print
*/
public void print(byte x) {
out.print(x);
out.flush();
}
/**
* Prints a formatted string to this output stream, using the specified format
* string and arguments, and then flushes this output stream.
*
* @param format the format string
* @param args the arguments accompanying the format string
*/
public void printf(String format, Object... args) {
out.printf(LOCALE, format, args);
out.flush();
}
/**
* Prints a formatted string to this output stream, using the specified
* locale, format string, and arguments, and then flushes this output stream.
*
* @param locale the locale
* @param format the format string
* @param args the arguments accompanying the format string
*/
public void printf(Locale locale, String format, Object... args) {
out.printf(locale, format, args);
out.flush();
}
/**
* A test client.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
Out out;
// write to stdout
out = new Out();
out.println("Test 1");
out.close();
// write to a file
out = new Out("test.txt");
out.println("Test 2");
out.close();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/

@ -0,0 +1,696 @@
/******************************************************************************
* Compilation: javac StdIn.java
* Execution: java StdIn (interactive test of basic functionality)
* Dependencies: none
*
* Reads in data of various types from standard input.
*
******************************************************************************/
package algs4.util;
import java.util.ArrayList;
import java.util.InputMismatchException;
import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.regex.Pattern;
/**
* The {@code StdIn} class provides static methods for reading strings
* and numbers from standard input.
* These functions fall into one of four categories:
* <ul>
* <li>those for reading individual tokens from standard input, one at a time,
* and converting each to a number, string, or boolean
* <li>those for reading characters from standard input, one at a time
* <li>those for reading lines from standard input, one at a time
* <li>those for reading a sequence of values of the same type from standard input,
* and returning the values in an array
* </ul>
* <p>
* Generally, it is best not to mix functions from the different
* categories in the same program.
* <p>
* <b>Getting started.</b>
* To use this class, you must have {@code StdIn.class} in your
* Java classpath. If you used our autoinstaller, you should be all set.
* Otherwise, either download
* <a href = "https://introcs.cs.princeton.edu/java/code/stdlib.jar">stdlib.jar</a>
* and add to your Java classpath or download
* <a href = "https://introcs.cs.princeton.edu/java/stdlib/StdIn.java">StdIn.java</a>
* and put a copy in your working directory.
* <p>
* <b>Reading tokens from standard input and converting to numbers and strings.</b>
* You can use the following methods to read numbers, strings, and booleans
* from standard input one at a time:
* <ul>
* <li> {@link #isEmpty()}
* <li> {@link #readInt()}
* <li> {@link #readDouble()}
* <li> {@link #readString()}
* <li> {@link #readShort()}
* <li> {@link #readLong()}
* <li> {@link #readFloat()}
* <li> {@link #readByte()}
* <li> {@link #readBoolean()}
* </ul>
* <p>
* The first method returns true if standard input has no more tokens.
* Each other method skips over any input that is whitespace. Then, it reads
* the next token and attempts to convert it into a value of the specified
* type. If it succeeds, it returns that value; otherwise, it
* throws an {@link InputMismatchException}.
* <p>
* <em>Whitespace</em> includes spaces, tabs, and newlines; the full definition
* is inherited from {@link Character#isWhitespace(char)}.
* A <em>token</em> is a maximal sequence of non-whitespace characters.
* The precise rules for describing which tokens can be converted to
* integers and floating-point numbers are inherited from
* <a href = "http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#number-syntax">Scanner</a>,
* using the locale {@link Locale#US}; the rules
* for floating-point numbers are slightly different
* from those in {@link Double#valueOf(String)},
* but unlikely to be of concern to most programmers.
* <p>
* As an example, the following code fragment reads integers from standard input,
* one at a time, and prints them one per line.
* <pre>
* while (!StdIn.isEmpty()) {
* double value = StdIn.readDouble();
* StdOut.println(value);
* }
* </pre>
* <p>
* <b>Reading characters from standard input.</b>
* You can use the following two methods to read characters from standard input one at a time:
* <ul>
* <li> {@link #hasNextChar()}
* <li> {@link #readChar()}
* </ul>
* <p>
* The first method returns true if standard input has more input (including whitespace).
* The second method reads and returns the next character of input on standard
* input (possibly a whitespace character).
* <p>
* As an example, the following code fragment reads characters from standard input,
* one character at a time, and prints it to standard output.
* <pre>
* while (StdIn.hasNextChar()) {
* char c = StdIn.readChar();
* StdOut.print(c);
* }
* </pre>
* <p>
* <b>Reading lines from standard input.</b>
* You can use the following two methods to read lines from standard input:
* <ul>
* <li> {@link #hasNextLine()}
* <li> {@link #readLine()}
* </ul>
* <p>
* The first method returns true if standard input has more input (including whitespace).
* The second method reads and returns the remaining portion of
* the next line of input on standard input (possibly whitespace),
* discarding the trailing line separator.
* <p>
* A <em>line separator</em> is defined to be one of the following strings:
* {@code \n} (Linux), {@code \r} (old Macintosh),
* {@code \r\n} (Windows),
* {@code \}{@code u2028}, {@code \}{@code u2029}, or {@code \}{@code u0085}.
* <p>
* As an example, the following code fragment reads text from standard input,
* one line at a time, and prints it to standard output.
* <pre>
* while (StdIn.hasNextLine()) {
* String line = StdIn.readLine();
* StdOut.println(line);
* }
* </pre>
* <p>
* <b>Reading a sequence of values of the same type from standard input.</b>
* You can use the following methods to read a sequence numbers, strings,
* or booleans (all of the same type) from standard input:
* <ul>
* <li> {@link #readAllDoubles()}
* <li> {@link #readAllInts()}
* <li> {@link #readAllLongs()}
* <li> {@link #readAllStrings()}
* <li> {@link #readAllLines()}
* <li> {@link #readAll()}
* </ul>
* <p>
* The first three methods read of all of remaining token on standard input
* and converts the tokens to values of
* the specified type, as in the corresponding
* {@code readDouble}, {@code readInt}, and {@code readString()} methods.
* The {@code readAllLines()} method reads all remaining lines on standard
* input and returns them as an array of strings.
* The {@code readAll()} method reads all remaining input on standard
* input and returns it as a string.
* <p>
* As an example, the following code fragment reads all of the remaining
* tokens from standard input and returns them as an array of strings.
* <pre>
* String[] words = StdIn.readAllStrings();
* </pre>
* <p>
* <b>Differences with Scanner.</b>
* {@code StdIn} and {@link Scanner} are both designed to parse
* tokens and convert them to primitive types and strings.
* The main differences are summarized below:
* <ul>
* <li> {@code StdIn} is a set of static methods and reads
* reads input from only standard input. It is suitable for use before
* a programmer knows about objects.
* See {@link In} for an object-oriented version that handles
* input from files, URLs,
* and sockets.
* <li> {@code StdIn} uses whitespace as the delimiter pattern
* that separates tokens.
* {@link Scanner} supports arbitrary delimiter patterns.
* <li> {@code StdIn} coerces the character-set encoding to UTF-8,
* which is the most widely used character encoding for Unicode.
* <li> {@code StdIn} coerces the locale to {@link Locale#US},
* for consistency with {@link StdOut}, {@link Double#parseDouble(String)},
* and floating-point literals.
* <li> {@code StdIn} has convenient methods for reading a single
* character; reading in sequences of integers, doubles, or strings;
* and reading in all of the remaining input.
* </ul>
* <p>
* Historical note: {@code StdIn} preceded {@code Scanner}; when
* {@code Scanner} was introduced, this class was re-implemented to use {@code Scanner}.
* <p>
* <b>Using standard input.</b>
* Standard input is a fundamental operating system abstraction on Mac OS X,
* Windows, and Linux.
* The methods in {@code StdIn} are <em>blocking</em>, which means that they
* will wait until you enter input on standard input.
* If your program has a loop that repeats until standard input is empty,
* you must signal that the input is finished.
* To do so, depending on your operating system and IDE,
* use either {@code <Ctrl-d>} or {@code <Ctrl-z>}, on its own line.
* If you are redirecting standard input from a file, you will not need
* to do anything to signal that the input is finished.
* <p>
* <b>Known bugs.</b>
* Java's UTF-8 encoding does not recognize the optional
* <a href = "http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058">byte-order mask</a>.
* If the input begins with the optional byte-order mask, {@code StdIn}
* will have an extra character {@code \}{@code uFEFF} at the beginning.
* <p>
* <b>Reference.</b>
* For additional documentation,
* see <a href="https://introcs.cs.princeton.edu/15inout">Section 1.5</a> of
* <em>Computer Science: An Interdisciplinary Approach</em>
* by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
* @author David Pritchard
*/
public final class StdIn {
/*** begin: section (1 of 2) of code duplicated from In to StdIn. */
// assume Unicode UTF-8 encoding
private static final String CHARSET_NAME = "UTF-8";
// assume language = English, country = US for consistency with System.out.
private static final Locale LOCALE = Locale.US;
// the default token separator; we maintain the invariant that this value
// is held by the scanner's delimiter between calls
private static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\p{javaWhitespace}+");
// makes whitespace significant
private static final Pattern EMPTY_PATTERN = Pattern.compile("");
// used to read the entire input
private static final Pattern EVERYTHING_PATTERN = Pattern.compile("\\A");
/*** end: section (1 of 2) of code duplicated from In to StdIn. */
private static Scanner scanner;
// it doesn't make sense to instantiate this class
private StdIn() { }
//// begin: section (2 of 2) of code duplicated from In to StdIn,
//// with all methods changed from "public" to "public static"
/**
* Returns true if standard input is empty (except possibly for whitespace).
* Use this method to know whether the next call to {@link #readString()},
* {@link #readDouble()}, etc will succeed.
*
* @return {@code true} if standard input is empty (except possibly
* for whitespace); {@code false} otherwise
*/
public static boolean isEmpty() {
return !scanner.hasNext();
}
/**
* Returns true if standard input has a next line.
* Use this method to know whether the
* next call to {@link #readLine()} will succeed.
* This method is functionally equivalent to {@link #hasNextChar()}.
*
* @return {@code true} if standard input has more input (including whitespace);
* {@code false} otherwise
*/
public static boolean hasNextLine() {
return scanner.hasNextLine();
}
/**
* Returns true if standard input has more input (including whitespace).
* Use this method to know whether the next call to {@link #readChar()} will succeed.
* This method is functionally equivalent to {@link #hasNextLine()}.
*
* @return {@code true} if standard input has more input (including whitespace);
* {@code false} otherwise
*/
public static boolean hasNextChar() {
scanner.useDelimiter(EMPTY_PATTERN);
boolean result = scanner.hasNext();
scanner.useDelimiter(WHITESPACE_PATTERN);
return result;
}
/**
* Reads and returns the next line, excluding the line separator if present.
*
* @return the next line, excluding the line separator if present;
* {@code null} if no such line
*/
public static String readLine() {
String line;
try {
line = scanner.nextLine();
}
catch (NoSuchElementException e) {
line = null;
}
return line;
}
/**
* Reads and returns the next character.
*
* @return the next {@code char}
* @throws NoSuchElementException if standard input is empty
*/
public static char readChar() {
try {
scanner.useDelimiter(EMPTY_PATTERN);
String ch = scanner.next();
assert ch.length() == 1 : "Internal (Std)In.readChar() error!"
+ " Please contact the authors.";
scanner.useDelimiter(WHITESPACE_PATTERN);
return ch.charAt(0);
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'char' value from standard input, "
+ "but no more tokens are available");
}
}
/**
* Reads and returns the remainder of the input, as a string.
*
* @return the remainder of the input, as a string
* @throws NoSuchElementException if standard input is empty
*/
public static String readAll() {
if (!scanner.hasNextLine())
return "";
String result = scanner.useDelimiter(EVERYTHING_PATTERN).next();
// not that important to reset delimeter, since now scanner is empty
scanner.useDelimiter(WHITESPACE_PATTERN); // but let's do it anyway
return result;
}
/**
* Reads the next token from standard input and returns it as a {@code String}.
*
* @return the next {@code String}
* @throws NoSuchElementException if standard input is empty
*/
public static String readString() {
try {
return scanner.next();
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'String' value from standard input, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from standard input, parses it as an integer, and returns the integer.
*
* @return the next integer on standard input
* @throws NoSuchElementException if standard input is empty
* @throws InputMismatchException if the next token cannot be parsed as an {@code int}
*/
public static int readInt() {
try {
return scanner.nextInt();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read an 'int' value from standard input, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attemps to read an 'int' value from standard input, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from standard input, parses it as a double, and returns the double.
*
* @return the next double on standard input
* @throws NoSuchElementException if standard input is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code double}
*/
public static double readDouble() {
try {
return scanner.nextDouble();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read a 'double' value from standard input, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'double' value from standard input, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from standard input, parses it as a float, and returns the float.
*
* @return the next float on standard input
* @throws NoSuchElementException if standard input is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code float}
*/
public static float readFloat() {
try {
return scanner.nextFloat();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read a 'float' value from standard input, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'float' value from standard input, "
+ "but there no more tokens are available");
}
}
/**
* Reads the next token from standard input, parses it as a long integer, and returns the long integer.
*
* @return the next long integer on standard input
* @throws NoSuchElementException if standard input is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code long}
*/
public static long readLong() {
try {
return scanner.nextLong();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read a 'long' value from standard input, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'long' value from standard input, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from standard input, parses it as a short integer, and returns the short integer.
*
* @return the next short integer on standard input
* @throws NoSuchElementException if standard input is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code short}
*/
public static short readShort() {
try {
return scanner.nextShort();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read a 'short' value from standard input, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'short' value from standard input, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from standard input, parses it as a byte, and returns the byte.
*
* @return the next byte on standard input
* @throws NoSuchElementException if standard input is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code byte}
*/
public static byte readByte() {
try {
return scanner.nextByte();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read a 'byte' value from standard input, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'byte' value from standard input, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from standard input, parses it as a boolean,
* and returns the boolean.
*
* @return the next boolean on standard input
* @throws NoSuchElementException if standard input is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code boolean}:
* {@code true} or {@code 1} for true, and {@code false} or {@code 0} for false,
* ignoring case
*/
public static boolean readBoolean() {
try {
String token = readString();
if ("true".equalsIgnoreCase(token)) return true;
if ("false".equalsIgnoreCase(token)) return false;
if ("1".equals(token)) return true;
if ("0".equals(token)) return false;
throw new InputMismatchException("attempts to read a 'boolean' value from standard input, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'boolean' value from standard input, "
+ "but no more tokens are available");
}
}
/**
* Reads all remaining tokens from standard input and returns them as an array of strings.
*
* @return all remaining tokens on standard input, as an array of strings
*/
public static String[] readAllStrings() {
// we could use readAll.trim().split(), but that's not consistent
// because trim() uses characters 0x00..0x20 as whitespace
String[] tokens = WHITESPACE_PATTERN.split(readAll());
if (tokens.length == 0 || tokens[0].length() > 0)
return tokens;
// don't include first token if it is leading whitespace
String[] decapitokens = new String[tokens.length-1];
for (int i = 0; i < tokens.length - 1; i++)
decapitokens[i] = tokens[i+1];
return decapitokens;
}
/**
* Reads all remaining lines from standard input and returns them as an array of strings.
* @return all remaining lines on standard input, as an array of strings
*/
public static String[] readAllLines() {
ArrayList<String> lines = new ArrayList<String>();
while (hasNextLine()) {
lines.add(readLine());
}
return lines.toArray(new String[lines.size()]);
}
/**
* Reads all remaining tokens from standard input, parses them as integers, and returns
* them as an array of integers.
* @return all remaining integers on standard input, as an array
* @throws InputMismatchException if any token cannot be parsed as an {@code int}
*/
public static int[] readAllInts() {
String[] fields = readAllStrings();
int[] vals = new int[fields.length];
for (int i = 0; i < fields.length; i++)
vals[i] = Integer.parseInt(fields[i]);
return vals;
}
/**
* Reads all remaining tokens from standard input, parses them as longs, and returns
* them as an array of longs.
* @return all remaining longs on standard input, as an array
* @throws InputMismatchException if any token cannot be parsed as a {@code long}
*/
public static long[] readAllLongs() {
String[] fields = readAllStrings();
long[] vals = new long[fields.length];
for (int i = 0; i < fields.length; i++)
vals[i] = Long.parseLong(fields[i]);
return vals;
}
/**
* Reads all remaining tokens from standard input, parses them as doubles, and returns
* them as an array of doubles.
* @return all remaining doubles on standard input, as an array
* @throws InputMismatchException if any token cannot be parsed as a {@code double}
*/
public static double[] readAllDoubles() {
String[] fields = readAllStrings();
double[] vals = new double[fields.length];
for (int i = 0; i < fields.length; i++)
vals[i] = Double.parseDouble(fields[i]);
return vals;
}
//// end: section (2 of 2) of code duplicated from In to StdIn
// do this once when StdIn is initialized
static {
resync();
}
/**
* If StdIn changes, use this to reinitialize the scanner.
*/
private static void resync() {
setScanner(new Scanner(new java.io.BufferedInputStream(System.in), CHARSET_NAME));
}
private static void setScanner(Scanner scanner) {
StdIn.scanner = scanner;
StdIn.scanner.useLocale(LOCALE);
}
/**
* Reads all remaining tokens, parses them as integers, and returns
* them as an array of integers.
* @return all remaining integers, as an array
* @throws InputMismatchException if any token cannot be parsed as an {@code int}
* @deprecated Replaced by {@link #readAllInts()}.
*/
@Deprecated
public static int[] readInts() {
return readAllInts();
}
/**
* Reads all remaining tokens, parses them as doubles, and returns
* them as an array of doubles.
* @return all remaining doubles, as an array
* @throws InputMismatchException if any token cannot be parsed as a {@code double}
* @deprecated Replaced by {@link #readAllDoubles()}.
*/
@Deprecated
public static double[] readDoubles() {
return readAllDoubles();
}
/**
* Reads all remaining tokens and returns them as an array of strings.
* @return all remaining tokens, as an array of strings
* @deprecated Replaced by {@link #readAllStrings()}.
*/
@Deprecated
public static String[] readStrings() {
return readAllStrings();
}
/**
* Interactive test of basic functionality.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
StdOut.print("Type a string: ");
String s = StdIn.readString();
StdOut.println("Your string was: " + s);
StdOut.println();
StdOut.print("Type an int: ");
int a = StdIn.readInt();
StdOut.println("Your int was: " + a);
StdOut.println();
StdOut.print("Type a boolean: ");
boolean b = StdIn.readBoolean();
StdOut.println("Your boolean was: " + b);
StdOut.println();
StdOut.print("Type a double: ");
double c = StdIn.readDouble();
StdOut.println("Your double was: " + c);
StdOut.println();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/

@ -0,0 +1,339 @@
/******************************************************************************
* Compilation: javac StdOut.java
* Execution: java StdOut
* Dependencies: none
*
* Writes data of various types to standard output.
*
******************************************************************************/
package algs4.util;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Locale;
/**
* This class provides methods for printing strings and numbers to standard output.
* <p>
* <b>Getting started.</b>
* To use this class, you must have {@code StdOut.class} in your
* Java classpath. If you used our autoinstaller, you should be all set.
* Otherwise, either download
* <a href = "https://introcs.cs.princeton.edu/java/code/stdlib.jar">stdlib.jar</a>
* and add to your Java classpath or download
* <a href = "https://introcs.cs.princeton.edu/java/stdlib/StdOut.java">StdOut.java</a>
* and put a copy in your working directory.
* <p>
* Here is an example program that uses {@code StdOut}:
* <pre>
* public class TestStdOut {
* public static void main(String[] args) {
* int a = 17;
* int b = 23;
* int sum = a + b;
* StdOut.println("Hello, World");
* StdOut.printf("%d + %d = %d\n", a, b, sum);
* }
* }
* </pre>
* <p>
* <b>Differences with System.out.</b>
* The behavior of {@code StdOut} is similar to that of {@link System#out},
* but there are a few technical differences:
* <ul>
* <li> {@code StdOut} coerces the character-set encoding to UTF-8,
* which is a standard character encoding for Unicode.
* <li> {@code StdOut} coerces the locale to {@link Locale#US},
* for consistency with {@link StdIn}, {@link Double#parseDouble(String)},
* and floating-point literals.
* <li> {@code StdOut} <em>flushes</em> standard output after each call to
* {@code print()} so that text will appear immediately in the terminal.
* </ul>
* <p>
* <b>Reference.</b>
* For additional documentation,
* see <a href="https://introcs.cs.princeton.edu/15inout">Section 1.5</a> of
* <em>Computer Science: An Interdisciplinary Approach</em>
* by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public final class StdOut {
// force Unicode UTF-8 encoding; otherwise it's system dependent
private static final String CHARSET_NAME = "UTF-8";
// assume language = English, country = US for consistency with StdIn
private static final Locale LOCALE = Locale.US;
// send output here
private static PrintWriter out;
// this is called before invoking any methods
static {
try {
out = new PrintWriter(new OutputStreamWriter(System.out, CHARSET_NAME), true);
}
catch (UnsupportedEncodingException e) {
System.out.println(e);
}
}
// don't instantiate
private StdOut() { }
/**
* Terminates the current line by printing the line-separator string.
*/
public static void println() {
out.println();
}
/**
* Prints an object to this output stream and then terminates the line.
*
* @param x the object to print
*/
public static void println(Object x) {
out.println(x);
}
/**
* Prints a boolean to standard output and then terminates the line.
*
* @param x the boolean to print
*/
public static void println(boolean x) {
out.println(x);
}
/**
* Prints a character to standard output and then terminates the line.
*
* @param x the character to print
*/
public static void println(char x) {
out.println(x);
}
/**
* Prints a double to standard output and then terminates the line.
*
* @param x the double to print
*/
public static void println(double x) {
out.println(x);
}
/**
* Prints an integer to standard output and then terminates the line.
*
* @param x the integer to print
*/
public static void println(float x) {
out.println(x);
}
/**
* Prints an integer to standard output and then terminates the line.
*
* @param x the integer to print
*/
public static void println(int x) {
out.println(x);
}
/**
* Prints a long to standard output and then terminates the line.
*
* @param x the long to print
*/
public static void println(long x) {
out.println(x);
}
/**
* Prints a short integer to standard output and then terminates the line.
*
* @param x the short to print
*/
public static void println(short x) {
out.println(x);
}
/**
* Prints a byte to standard output and then terminates the line.
* <p>
* To write binary data, see {@link BinaryStdOut}.
*
* @param x the byte to print
*/
public static void println(byte x) {
out.println(x);
}
/**
* Flushes standard output.
*/
public static void print() {
out.flush();
}
/**
* Prints an object to standard output and flushes standard output.
*
* @param x the object to print
*/
public static void print(Object x) {
out.print(x);
out.flush();
}
/**
* Prints a boolean to standard output and flushes standard output.
*
* @param x the boolean to print
*/
public static void print(boolean x) {
out.print(x);
out.flush();
}
/**
* Prints a character to standard output and flushes standard output.
*
* @param x the character to print
*/
public static void print(char x) {
out.print(x);
out.flush();
}
/**
* Prints a double to standard output and flushes standard output.
*
* @param x the double to print
*/
public static void print(double x) {
out.print(x);
out.flush();
}
/**
* Prints a float to standard output and flushes standard output.
*
* @param x the float to print
*/
public static void print(float x) {
out.print(x);
out.flush();
}
/**
* Prints an integer to standard output and flushes standard output.
*
* @param x the integer to print
*/
public static void print(int x) {
out.print(x);
out.flush();
}
/**
* Prints a long integer to standard output and flushes standard output.
*
* @param x the long integer to print
*/
public static void print(long x) {
out.print(x);
out.flush();
}
/**
* Prints a short integer to standard output and flushes standard output.
*
* @param x the short integer to print
*/
public static void print(short x) {
out.print(x);
out.flush();
}
/**
* Prints a byte to standard output and flushes standard output.
*
* @param x the byte to print
*/
public static void print(byte x) {
out.print(x);
out.flush();
}
/**
* Prints a formatted string to standard output, using the specified format
* string and arguments, and then flushes standard output.
*
*
* @param format the <a href = "http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax">format string</a>
* @param args the arguments accompanying the format string
*/
public static void printf(String format, Object... args) {
out.printf(LOCALE, format, args);
out.flush();
}
/**
* Prints a formatted string to standard output, using the locale and
* the specified format string and arguments; then flushes standard output.
*
* @param locale the locale
* @param format the <a href = "http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax">format string</a>
* @param args the arguments accompanying the format string
*/
public static void printf(Locale locale, String format, Object... args) {
out.printf(locale, format, args);
out.flush();
}
/**
* Unit tests some of the methods in {@code StdOut}.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
// write to stdout
StdOut.println("Test");
StdOut.println(17);
StdOut.println(true);
StdOut.printf("%.6f\n", 1.0/7.0);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/

@ -0,0 +1,674 @@
/******************************************************************************
* Compilation: javac StdRandom.java
* Execution: java StdRandom
* Dependencies: StdOut.java
*
* A library of static methods to generate pseudo-random numbers from
* different distributions (bernoulli, uniform, gaussian, discrete,
* and exponential). Also includes a method for shuffling an array.
*
*
* % java StdRandom 5
* seed = 1316600602069
* 59 16.81826 true 8.83954 0
* 32 91.32098 true 9.11026 0
* 35 10.11874 true 8.95396 3
* 92 32.88401 true 8.87089 0
* 72 92.55791 true 9.46241 0
*
* % java StdRandom 5
* seed = 1316600616575
* 96 60.17070 true 8.72821 0
* 79 32.01607 true 8.58159 0
* 81 59.49065 true 9.10423 1
* 96 51.65818 true 9.02102 0
* 99 17.55771 true 8.99762 0
*
* % java StdRandom 5 1316600616575
* seed = 1316600616575
* 96 60.17070 true 8.72821 0
* 79 32.01607 true 8.58159 0
* 81 59.49065 true 9.10423 1
* 96 51.65818 true 9.02102 0
* 99 17.55771 true 8.99762 0
*
*
* Remark
* ------
* - Relies on randomness of nextDouble() method in java.util.Random
* to generate pseudo-random numbers in [0, 1).
*
* - This library allows you to set and get the pseudo-random number seed.
*
* - See http://www.honeylocust.com/RngPack/ for an industrial
* strength random number generator in Java.
*
******************************************************************************/
package algs4.util;
import java.util.Random;
/**
* The {@code StdRandom} class provides static methods for generating
* random number from various discrete and continuous distributions,
* including uniform, Bernoulli, geometric, Gaussian, exponential, Pareto,
* Poisson, and Cauchy. It also provides method for shuffling an
* array or subarray and generating random permutations.
* <p>
* By convention, all intervals are half open. For example,
* <code>uniform(-1.0, 1.0)</code> returns a random number between
* <code>-1.0</code> (inclusive) and <code>1.0</code> (exclusive).
* Similarly, <code>shuffle(a, lo, hi)</code> shuffles the <code>hi - lo</code>
* elements in the array <code>a[]</code>, starting at index <code>lo</code>
* (inclusive) and ending at index <code>hi</code> (exclusive).
* <p>
* For additional documentation,
* see <a href="https://introcs.cs.princeton.edu/22library">Section 2.2</a> of
* <i>Computer Science: An Interdisciplinary Approach</i>
* by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public final class StdRandom {
private static Random random; // pseudo-random number generator
private static long seed; // pseudo-random number generator seed
// static initializer
static {
// this is how the seed was set in Java 1.4
seed = System.currentTimeMillis();
random = new Random(seed);
}
// don't instantiate
private StdRandom() { }
/**
* Sets the seed of the pseudo-random number generator.
* This method enables you to produce the same sequence of "random"
* number for each execution of the program.
* Ordinarily, you should call this method at most once per program.
*
* @param s the seed
*/
public static void setSeed(long s) {
seed = s;
random = new Random(seed);
}
/**
* Returns the seed of the pseudo-random number generator.
*
* @return the seed
*/
public static long getSeed() {
return seed;
}
/**
* Returns a random real number uniformly in [0, 1).
*
* @return a random real number uniformly in [0, 1)
*/
public static double uniform() {
return random.nextDouble();
}
/**
* Returns a random integer uniformly in [0, n).
*
* @param n number of possible integers
* @return a random integer uniformly between 0 (inclusive) and {@code n} (exclusive)
* @throws IllegalArgumentException if {@code n <= 0}
*/
public static int uniform(int n) {
if (n <= 0) throw new IllegalArgumentException("argument must be positive: " + n);
return random.nextInt(n);
}
/**
* Returns a random long integer uniformly in [0, n).
*
* @param n number of possible {@code long} integers
* @return a random long integer uniformly between 0 (inclusive) and {@code n} (exclusive)
* @throws IllegalArgumentException if {@code n <= 0}
*/
public static long uniform(long n) {
if (n <= 0L) throw new IllegalArgumentException("argument must be positive: " + n);
// https://docs.oracle.com/javase/8/docs/api/java/util/Random.html#longs-long-long-long-
long r = random.nextLong();
long m = n - 1;
// power of two
if ((n & m) == 0L) {
return r & m;
}
// reject over-represented candidates
long u = r >>> 1;
while (u + m - (r = u % n) < 0L) {
u = random.nextLong() >>> 1;
}
return r;
}
///////////////////////////////////////////////////////////////////////////
// STATIC METHODS BELOW RELY ON JAVA.UTIL.RANDOM ONLY INDIRECTLY VIA
// THE STATIC METHODS ABOVE.
///////////////////////////////////////////////////////////////////////////
/**
* Returns a random real number uniformly in [0, 1).
*
* @return a random real number uniformly in [0, 1)
* @deprecated Replaced by {@link #uniform()}.
*/
@Deprecated
public static double random() {
return uniform();
}
/**
* Returns a random integer uniformly in [a, b).
*
* @param a the left endpoint
* @param b the right endpoint
* @return a random integer uniformly in [a, b)
* @throws IllegalArgumentException if {@code b <= a}
* @throws IllegalArgumentException if {@code b - a >= Integer.MAX_VALUE}
*/
public static int uniform(int a, int b) {
if ((b <= a) || ((long) b - a >= Integer.MAX_VALUE)) {
throw new IllegalArgumentException("invalid range: [" + a + ", " + b + ")");
}
return a + uniform(b - a);
}
/**
* Returns a random real number uniformly in [a, b).
*
* @param a the left endpoint
* @param b the right endpoint
* @return a random real number uniformly in [a, b)
* @throws IllegalArgumentException unless {@code a < b}
*/
public static double uniform(double a, double b) {
if (!(a < b)) {
throw new IllegalArgumentException("invalid range: [" + a + ", " + b + ")");
}
return a + uniform() * (b-a);
}
/**
* Returns a random boolean from a Bernoulli distribution with success
* probability <em>p</em>.
*
* @param p the probability of returning {@code true}
* @return {@code true} with probability {@code p} and
* {@code false} with probability {@code 1 - p}
* @throws IllegalArgumentException unless {@code 0} &le; {@code p} &le; {@code 1.0}
*/
public static boolean bernoulli(double p) {
if (!(p >= 0.0 && p <= 1.0))
throw new IllegalArgumentException("probability p must be between 0.0 and 1.0: " + p);
return uniform() < p;
}
/**
* Returns a random boolean from a Bernoulli distribution with success
* probability 1/2.
*
* @return {@code true} with probability 1/2 and
* {@code false} with probability 1/2
*/
public static boolean bernoulli() {
return bernoulli(0.5);
}
/**
* Returns a random real number from a standard Gaussian distribution.
*
* @return a random real number from a standard Gaussian distribution
* (mean 0 and standard deviation 1).
*/
public static double gaussian() {
// use the polar form of the Box-Muller transform
double r, x, y;
do {
x = uniform(-1.0, 1.0);
y = uniform(-1.0, 1.0);
r = x*x + y*y;
} while (r >= 1 || r == 0);
return x * Math.sqrt(-2 * Math.log(r) / r);
// Remark: y * Math.sqrt(-2 * Math.log(r) / r)
// is an independent random gaussian
}
/**
* Returns a random real number from a Gaussian distribution with mean &mu;
* and standard deviation &sigma;.
*
* @param mu the mean
* @param sigma the standard deviation
* @return a real number distributed according to the Gaussian distribution
* with mean {@code mu} and standard deviation {@code sigma}
*/
public static double gaussian(double mu, double sigma) {
return mu + sigma * gaussian();
}
/**
* Returns a random integer from a geometric distribution with success
* probability <em>p</em>.
* The integer represents the number of independent trials
* before the first success.
*
* @param p the parameter of the geometric distribution
* @return a random integer from a geometric distribution with success
* probability {@code p}; or {@code Integer.MAX_VALUE} if
* {@code p} is (nearly) equal to {@code 1.0}.
* @throws IllegalArgumentException unless {@code p >= 0.0} and {@code p <= 1.0}
*/
public static int geometric(double p) {
if (!(p >= 0)) {
throw new IllegalArgumentException("probability p must be greater than 0: " + p);
}
if (!(p <= 1.0)) {
throw new IllegalArgumentException("probability p must not be larger than 1: " + p);
}
// using algorithm given by Knuth
return (int) Math.ceil(Math.log(uniform()) / Math.log(1.0 - p));
}
/**
* Returns a random integer from a Poisson distribution with mean &lambda;.
*
* @param lambda the mean of the Poisson distribution
* @return a random integer from a Poisson distribution with mean {@code lambda}
* @throws IllegalArgumentException unless {@code lambda > 0.0} and not infinite
*/
public static int poisson(double lambda) {
if (!(lambda > 0.0))
throw new IllegalArgumentException("lambda must be positive: " + lambda);
if (Double.isInfinite(lambda))
throw new IllegalArgumentException("lambda must not be infinite: " + lambda);
// using algorithm given by Knuth
// see http://en.wikipedia.org/wiki/Poisson_distribution
int k = 0;
double p = 1.0;
double expLambda = Math.exp(-lambda);
do {
k++;
p *= uniform();
} while (p >= expLambda);
return k-1;
}
/**
* Returns a random real number from the standard Pareto distribution.
*
* @return a random real number from the standard Pareto distribution
*/
public static double pareto() {
return pareto(1.0);
}
/**
* Returns a random real number from a Pareto distribution with
* shape parameter &alpha;.
*
* @param alpha shape parameter
* @return a random real number from a Pareto distribution with shape
* parameter {@code alpha}
* @throws IllegalArgumentException unless {@code alpha > 0.0}
*/
public static double pareto(double alpha) {
if (!(alpha > 0.0))
throw new IllegalArgumentException("alpha must be positive: " + alpha);
return Math.pow(1 - uniform(), -1.0/alpha) - 1.0;
}
/**
* Returns a random real number from the Cauchy distribution.
*
* @return a random real number from the Cauchy distribution.
*/
public static double cauchy() {
return Math.tan(Math.PI * (uniform() - 0.5));
}
/**
* Returns a random integer from the specified discrete distribution.
*
* @param probabilities the probability of occurrence of each integer
* @return a random integer from a discrete distribution:
* {@code i} with probability {@code probabilities[i]}
* @throws IllegalArgumentException if {@code probabilities} is {@code null}
* @throws IllegalArgumentException if sum of array entries is not (very nearly) equal to {@code 1.0}
* @throws IllegalArgumentException unless {@code probabilities[i] >= 0.0} for each index {@code i}
*/
public static int discrete(double[] probabilities) {
if (probabilities == null) throw new IllegalArgumentException("argument array must not be null");
double EPSILON = 1.0E-14;
double sum = 0.0;
for (int i = 0; i < probabilities.length; i++) {
if (!(probabilities[i] >= 0.0))
throw new IllegalArgumentException("array entry " + i + " must be non-negative: " + probabilities[i]);
sum += probabilities[i];
}
if (sum > 1.0 + EPSILON || sum < 1.0 - EPSILON)
throw new IllegalArgumentException("sum of array entries does not approximately equal 1.0: " + sum);
// the for loop may not return a value when both r is (nearly) 1.0 and when the
// cumulative sum is less than 1.0 (as a result of floating-point roundoff error)
while (true) {
double r = uniform();
sum = 0.0;
for (int i = 0; i < probabilities.length; i++) {
sum = sum + probabilities[i];
if (sum > r) return i;
}
}
}
/**
* Returns a random integer from the specified discrete distribution.
*
* @param frequencies the frequency of occurrence of each integer
* @return a random integer from a discrete distribution:
* {@code i} with probability proportional to {@code frequencies[i]}
* @throws IllegalArgumentException if {@code frequencies} is {@code null}
* @throws IllegalArgumentException if all array entries are {@code 0}
* @throws IllegalArgumentException if {@code frequencies[i]} is negative for any index {@code i}
* @throws IllegalArgumentException if sum of frequencies exceeds {@code Integer.MAX_VALUE} (2<sup>31</sup> - 1)
*/
public static int discrete(int[] frequencies) {
if (frequencies == null) throw new IllegalArgumentException("argument array must not be null");
long sum = 0;
for (int i = 0; i < frequencies.length; i++) {
if (frequencies[i] < 0)
throw new IllegalArgumentException("array entry " + i + " must be non-negative: " + frequencies[i]);
sum += frequencies[i];
}
if (sum == 0)
throw new IllegalArgumentException("at least one array entry must be positive");
if (sum >= Integer.MAX_VALUE)
throw new IllegalArgumentException("sum of frequencies overflows an int");
// pick index i with probabilitity proportional to frequency
double r = uniform((int) sum);
sum = 0;
for (int i = 0; i < frequencies.length; i++) {
sum += frequencies[i];
if (sum > r) return i;
}
// can't reach here
assert false;
return -1;
}
/**
* Returns a random real number from an exponential distribution
* with rate &lambda;.
*
* @param lambda the rate of the exponential distribution
* @return a random real number from an exponential distribution with
* rate {@code lambda}
* @throws IllegalArgumentException unless {@code lambda > 0.0}
*/
public static double exp(double lambda) {
if (!(lambda > 0.0))
throw new IllegalArgumentException("lambda must be positive: " + lambda);
return -Math.log(1 - uniform()) / lambda;
}
/**
* Rearranges the elements of the specified array in uniformly random order.
*
* @param a the array to shuffle
* @throws IllegalArgumentException if {@code a} is {@code null}
*/
public static void shuffle(Object[] a) {
validateNotNull(a);
int n = a.length;
for (int i = 0; i < n; i++) {
int r = i + uniform(n-i); // between i and n-1
Object temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* Rearranges the elements of the specified array in uniformly random order.
*
* @param a the array to shuffle
* @throws IllegalArgumentException if {@code a} is {@code null}
*/
public static void shuffle(double[] a) {
validateNotNull(a);
int n = a.length;
for (int i = 0; i < n; i++) {
int r = i + uniform(n-i); // between i and n-1
double temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* Rearranges the elements of the specified array in uniformly random order.
*
* @param a the array to shuffle
* @throws IllegalArgumentException if {@code a} is {@code null}
*/
public static void shuffle(int[] a) {
validateNotNull(a);
int n = a.length;
for (int i = 0; i < n; i++) {
int r = i + uniform(n-i); // between i and n-1
int temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* Rearranges the elements of the specified array in uniformly random order.
*
* @param a the array to shuffle
* @throws IllegalArgumentException if {@code a} is {@code null}
*/
public static void shuffle(char[] a) {
validateNotNull(a);
int n = a.length;
for (int i = 0; i < n; i++) {
int r = i + uniform(n-i); // between i and n-1
char temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* Rearranges the elements of the specified subarray in uniformly random order.
*
* @param a the array to shuffle
* @param lo the left endpoint (inclusive)
* @param hi the right endpoint (exclusive)
* @throws IllegalArgumentException if {@code a} is {@code null}
* @throws IllegalArgumentException unless {@code (0 <= lo) && (lo < hi) && (hi <= a.length)}
*
*/
public static void shuffle(Object[] a, int lo, int hi) {
validateNotNull(a);
validateSubarrayIndices(lo, hi, a.length);
for (int i = lo; i < hi; i++) {
int r = i + uniform(hi-i); // between i and hi-1
Object temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* Rearranges the elements of the specified subarray in uniformly random order.
*
* @param a the array to shuffle
* @param lo the left endpoint (inclusive)
* @param hi the right endpoint (exclusive)
* @throws IllegalArgumentException if {@code a} is {@code null}
* @throws IllegalArgumentException unless {@code (0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public static void shuffle(double[] a, int lo, int hi) {
validateNotNull(a);
validateSubarrayIndices(lo, hi, a.length);
for (int i = lo; i < hi; i++) {
int r = i + uniform(hi-i); // between i and hi-1
double temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* Rearranges the elements of the specified subarray in uniformly random order.
*
* @param a the array to shuffle
* @param lo the left endpoint (inclusive)
* @param hi the right endpoint (exclusive)
* @throws IllegalArgumentException if {@code a} is {@code null}
* @throws IllegalArgumentException unless {@code (0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public static void shuffle(int[] a, int lo, int hi) {
validateNotNull(a);
validateSubarrayIndices(lo, hi, a.length);
for (int i = lo; i < hi; i++) {
int r = i + uniform(hi-i); // between i and hi-1
int temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* Returns a uniformly random permutation of <em>n</em> elements.
*
* @param n number of elements
* @throws IllegalArgumentException if {@code n} is negative
* @return an array of length {@code n} that is a uniformly random permutation
* of {@code 0}, {@code 1}, ..., {@code n-1}
*/
public static int[] permutation(int n) {
if (n < 0) throw new IllegalArgumentException("n must be non-negative: " + n);
int[] perm = new int[n];
for (int i = 0; i < n; i++)
perm[i] = i;
shuffle(perm);
return perm;
}
/**
* Returns a uniformly random permutation of <em>k</em> of <em>n</em> elements.
*
* @param n number of elements
* @param k number of elements to select
* @throws IllegalArgumentException if {@code n} is negative
* @throws IllegalArgumentException unless {@code 0 <= k <= n}
* @return an array of length {@code k} that is a uniformly random permutation
* of {@code k} of the elements from {@code 0}, {@code 1}, ..., {@code n-1}
*/
public static int[] permutation(int n, int k) {
if (n < 0) throw new IllegalArgumentException("n must be non-negative: " + n);
if (k < 0 || k > n) throw new IllegalArgumentException("k must be between 0 and n: " + k);
int[] perm = new int[k];
for (int i = 0; i < k; i++) {
int r = uniform(i+1); // between 0 and i
perm[i] = perm[r];
perm[r] = i;
}
for (int i = k; i < n; i++) {
int r = uniform(i+1); // between 0 and i
if (r < k) perm[r] = i;
}
return perm;
}
// throw an IllegalArgumentException if x is null
// (x can be of type Object[], double[], int[], ...)
private static void validateNotNull(Object x) {
if (x == null) {
throw new IllegalArgumentException("argument must not be null");
}
}
// throw an exception unless 0 <= lo <= hi <= length
private static void validateSubarrayIndices(int lo, int hi, int length) {
if (lo < 0 || hi > length || lo > hi) {
throw new IllegalArgumentException("subarray indices out of bounds: [" + lo + ", " + hi + ")");
}
}
/**
* Unit tests the methods in this class.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
if (args.length == 2) StdRandom.setSeed(Long.parseLong(args[1]));
double[] probabilities = { 0.5, 0.3, 0.1, 0.1 };
int[] frequencies = { 5, 3, 1, 1 };
String[] a = "A B C D E F G".split(" ");
StdOut.println("seed = " + StdRandom.getSeed());
for (int i = 0; i < n; i++) {
StdOut.printf("%2d ", uniform(100));
StdOut.printf("%8.5f ", uniform(10.0, 99.0));
StdOut.printf("%5b ", bernoulli(0.5));
StdOut.printf("%7.5f ", gaussian(9.0, 0.2));
StdOut.printf("%1d ", discrete(probabilities));
StdOut.printf("%1d ", discrete(frequencies));
StdOut.printf("%11d ", uniform(100000000000L));
StdRandom.shuffle(a);
for (String s : a)
StdOut.print(s);
StdOut.println();
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/

@ -0,0 +1,110 @@
/******************************************************************************
* Compilation: javac Stopwatch.java
* Execution: java Stopwatch n
* Dependencies: none
*
* A utility class to measure the running time (wall clock) of a program.
*
* % java8 Stopwatch 100000000
* 6.666667e+11 0.5820 seconds
* 6.666667e+11 8.4530 seconds
*
******************************************************************************/
package algs4.util;
/**
* The {@code Stopwatch} data type is for measuring
* the time that elapses between the start and end of a
* programming task (wall-clock time).
*
* See {@link StopwatchCPU} for a version that measures CPU time.
* For additional documentation,
* see <a href="https://algs4.cs.princeton.edu/14analysis">Section 1.4</a> of
* <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class Stopwatch {
private final long start;
/**
* Initializes a new stopwatch.
*/
public Stopwatch() {
start = System.currentTimeMillis();
}
/**
* Returns the elapsed CPU time (in seconds) since the stopwatch was created.
*
* @return elapsed CPU time (in seconds) since the stopwatch was created
*/
public double elapsedTime() {
long now = System.currentTimeMillis();
return (now - start) / 1000.0;
}
/**
* Unit tests the {@code Stopwatch} data type.
* Takes a command-line argument {@code n} and computes the
* sum of the square roots of the first {@code n} positive integers,
* first using {@code Math.sqrt()}, then using {@code Math.pow()}.
* It prints to standard output the sum and the amount of time to
* compute the sum. Note that the discrete sum can be approximated by
* an integral - the sum should be approximately 2/3 * (n^(3/2) - 1).
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
// sum of square roots of integers from 1 to n using Math.sqrt(x).
Stopwatch timer1 = new Stopwatch();
double sum1 = 0.0;
for (int i = 1; i <= n; i++) {
sum1 += Math.sqrt(i);
}
double time1 = timer1.elapsedTime();
StdOut.printf("%e (%.2f seconds)\n", sum1, time1);
// sum of square roots of integers from 1 to n using Math.pow(x, 0.5).
Stopwatch timer2 = new Stopwatch();
double sum2 = 0.0;
for (int i = 1; i <= n; i++) {
sum2 += Math.pow(i, 0.5);
}
double time2 = timer2.elapsedTime();
StdOut.printf("%e (%.2f seconds)\n", sum2, time2);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/

@ -0,0 +1,112 @@
/******************************************************************************
* Compilation: javac StopwatchCPU.java
* Execution: java StopwtachCPU n
* Dependencies: none
*
* A version of Stopwatch.java that measures CPU time on a single
* core or processor (instead of wall clock time).
*
* % java8 StopwatchCPU 100000000
* 6.666667e+11 (1.05 seconds)
* 6.666667e+11 (7.50 seconds)
*
******************************************************************************/
package algs4.util;
import java.lang.management.ThreadMXBean;
import java.lang.management.ManagementFactory;
/**
* The {@code StopwatchCPU} data type is for measuring
* the CPU time used during a programming task.
*
* See {@link Stopwatch} for a version that measures wall-clock time
* (the real time that elapses).
*
* @author Josh Hug
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class StopwatchCPU {
private static final double NANOSECONDS_PER_SECOND = 1_000_000_000;
private final ThreadMXBean threadTimer;
private final long start;
/**
* Initializes a new stopwatch.
*/
public StopwatchCPU() {
threadTimer = ManagementFactory.getThreadMXBean();
start = threadTimer.getCurrentThreadCpuTime();
}
/**
* Returns the elapsed CPU time (in seconds) since the stopwatch was created.
*
* @return elapsed CPU time (in seconds) since the stopwatch was created
*/
public double elapsedTime() {
long now = threadTimer.getCurrentThreadCpuTime();
return (now - start) / NANOSECONDS_PER_SECOND;
}
/**
* Unit tests the {@code StopwatchCPU} data type.
* Takes a command-line argument {@code n} and computes the
* sum of the square roots of the first {@code n} positive integers,
* first using {@code Math.sqrt()}, then using {@code Math.pow()}.
* It prints to standard output the sum and the amount of time to
* compute the sum. Note that the discrete sum can be approximated by
* an integral - the sum should be approximately 2/3 * (n^(3/2) - 1).
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
// sum of square roots of integers from 1 to n using Math.sqrt(x).
StopwatchCPU timer1 = new StopwatchCPU();
double sum1 = 0.0;
for (int i = 1; i <= n; i++) {
sum1 += Math.sqrt(i);
}
double time1 = timer1.elapsedTime();
StdOut.printf("%e (%.2f seconds)\n", sum1, time1);
// sum of square roots of integers from 1 to n using Math.pow(x, 0.5).
StopwatchCPU timer2 = new StopwatchCPU();
double sum2 = 0.0;
for (int i = 1; i <= n; i++) {
sum2 += Math.pow(i, 0.5);
}
double time2 = timer2.elapsedTime();
StdOut.printf("%e (%.2f seconds)\n", sum2, time2);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/

@ -0,0 +1,6 @@
package core.problem;
public abstract class Action {
public abstract void draw();
public abstract int stepCost();
}

@ -0,0 +1,143 @@
package core.problem;
import core.solver.Node;
import core.solver.heuristic.Predictor;
import java.util.ArrayList;
import java.util.Deque;
/**
*
* initialState
* goal
*/
public abstract class Problem {
//成员变量
protected State initialState;
protected State goal;
protected int size; //问题的规模15-puzzle为4寻路问题为Grid的边长野人传教士为野人与传教士的人数
public Problem(State initialState, State goal) {
this.initialState = initialState;
this.goal = goal;
}
public Problem(State initialState, State goal, int size) {
this(initialState, goal);
this.size = size;
}
public State getInitialState() {
return initialState;
}
public State getGoal() {
return goal;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public void setInitialState(State initialState) {
this.initialState = initialState;
}
public void setGoal(State goal) {
this.goal = goal;
}
/**
*
* @return true; false
*
*/
public abstract boolean solvable();
/**
*
* @param predictor
* @return
*/
public final Node root(Predictor predictor) {
return new Node(initialState, null, null,
0, predictor.heuristics(initialState, goal));
}
/**
* node
* @param parent
* @param predictor
*
* @return parent
*/
public final Iterable<? extends Node> childNodes(Node parent, Predictor predictor) {
ArrayList<Node> nodes = new ArrayList<>();
//父结点的状态
State parentState = parent.getState();
//对于parentState上所有可能的action但有的不可行
for (Action action : parentState.actions()){
//如果父结点状态下的动作是可行的
if (applicable(parentState, action)){
//得到后继状态
State state = parentState.next(action);
//计算路径长度 = 父结点路径长度 + 进入后继状态所采取的动作的代价
int pathCost = parent.getPathCost() + stepCost(state, action);
//使用predictor对state与goal的距离进行估值
int heuristics = predictor.heuristics(state, goal);
//生成子结点
Node child = new Node(state, parent, action, pathCost, heuristics);
nodes.add(child);
}
}
return nodes;
}
/**
*
* @param state
* @param action Action
* @return
*/
public abstract int stepCost(State state, Action action);
/**
* stateaction
* @param state
* @param action
* @return truefalse
*/
protected abstract boolean applicable(State state, Action action);
/**
* state
*
* @param state
* @return truefalse
*/
public boolean goal(State state){
return state.equals(goal);
}
/**
*
* @param path
*/
public abstract void showSolution(Deque<Node> path);
/**
*
*/
public abstract void draw();
/**
*
* @param path
*/
public abstract void printPath(Deque<Node> path);
}

@ -0,0 +1,24 @@
package core.problem;
import g04.problem.npuzzle.PuzzleState;
/**
*
*/
public abstract class State {
public abstract void draw(); // 在Console上输出该状态
/**
* action
* @param action action
* @return
*/
public abstract State next(Action action);
/**
* Action
* @return Action
*/
public abstract Iterable<? extends Action> actions();
}

@ -0,0 +1,85 @@
package core.runner;
import core.problem.Problem;
import core.problem.State;
import core.solver.Searcher;
import core.solver.heuristic.AbstractFrontier;
import core.solver.heuristic.BestFirstSearch;
import core.solver.heuristic.EvaluationType;
import core.solver.heuristic.Predictor;
import algs4.util.In;
import g04.problem.npuzzle.PuzzleState;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
/**
*
* problem
* 使Frontier
* 使 h
* IDA Star
*
*/
public abstract class EngineFeeder {
/**
* NPuzzle
* @param io
* @return NPuzzle
*/
public abstract ArrayList<Problem> getProblems(In io);
public abstract ArrayList<Problem> getProblems(Scanner scanner);
/**
* Frontier
* @param type
* @return 使Frontier
*/
public abstract AbstractFrontier getFrontier(EvaluationType type);
/**
* Predictor
* @param type
* @return
*/
public abstract Predictor getPredictor(HeuristicType type);
/**
* IdaStar
*/
public abstract Searcher getIdaStar();
/**
* Searcher
* @return
*/
public abstract Searcher getScoreSearcher();
/**
* AStar,
* 使AStar
*/
public Searcher getAStar(HeuristicType type){
//获取Frontier其Node以g(n)+h(n)的升序排列
AbstractFrontier frontier = getFrontier(EvaluationType.FULL);
//以HashSet作为Explored表
Set<State> explored = new HashSet<>();
//根据explored和frontier生成AStar引擎并使用类型为type的启发函数
return new BestFirstSearch(explored, frontier, PuzzleState.predictor(type));
}
/**
* Dijkstra
* @return Dijkstra
*/
public Searcher getDijkstra(){
//获取Frontier其Node以g(n)+h(n)的升序排列
AbstractFrontier frontier = getFrontier(EvaluationType.PATH_COST);
//以HashSet作为Explored表
Set<State> explored = new HashSet<>();
//根据explored和frontier生成AStar引擎并使用曼哈顿距离作为启发函数
return new BestFirstSearch(explored, frontier, (state, goal) -> 0);
}
}

@ -0,0 +1,16 @@
package core.runner;
public enum HeuristicType {
//Npuzzle的启发函数
MISPLACED, // 不在位将牌
MANHATTAN, // 曼哈顿距离
DISJOINT_PATTERN,
//PathFinding的启发函数 (8方向的情况)
PF_EUCLID, // 欧几里得距离
PF_MANHATTAN, // 8方向移动时不是admissible的
PF_GRID, // 尽可能走对角线,然后平行走,>= EUCLID
//野人传教士问题
MC_HARMONY //去掉野人会吃人的约束
}

@ -0,0 +1,8 @@
package core.runner;
public enum ProblemType {
NPUZZLE, // NPuzzle问题
PATHFINDING, // 寻路问题
SLIDING_BLOCKS, // 滑动积木块问题
MISSIONARY_AND_CARNIVAL //野人传教士问题
}

@ -0,0 +1,74 @@
package core.runner;
import algs4.util.Stopwatch;
import core.problem.Problem;
import core.solver.Node;
import algs4.util.In;
import core.solver.heuristic.BestFirstSearch;
import g04.problem.npuzzle.MyFeeder;
import g04.solver.heuristic.IDAStarSearch;
import java.util.ArrayList;
import java.util.Deque;
public class SearchRunner {
public static void main(String[] args) {
//从文件中读入问题的实例,寻路问题
In problemInput = new In("resources/pathfinding.txt");
//生成一个具体的EngineFeederFeederXu引擎饲养员徐老师:)
EngineFeeder feeder = new MyFeeder();
//feeder从文件获取所有问题实例
ArrayList<Problem> problems = feeder.getProblems(problemInput);
//从Feeder获取所使用的搜索引擎 AStar
/*
BestFirstSearch astar = (BestFirstSearch) feeder.getScoreSearcher();
for (Problem problem : problems){
Stopwatch stopwatch = new Stopwatch();
//使用AStar引擎求解问题
Deque<Node> path = astar.search(problem);
//解的可视化
problem.showSolution(path);
//仅打印路径
problem.printPath(path);
System.out.println(astar.expandedNode());
System.out.println(path.size());
System.out.println(stopwatch.elapsedTime());
}
System.out.println("==============================================================");
*/
//从Feeder获取所使用的搜索引擎 IDAStar
IDAStarSearch idastar = (IDAStarSearch) feeder.getIdaStar();
for (Problem problem : problems){
Stopwatch stopwatch = new Stopwatch();
//使用AStar引擎求解问题
Deque<Node> path = idastar.search(problem);
//解的可视化
problem.showSolution(path);
//仅打印路径
//problem.printPath(path);
System.out.println(path.size());
System.out.println(stopwatch.elapsedTime());
System.out.println("==============================================================");
}
//从Feeder获取所使用的搜索引擎 Dijkstra
/*
BestFirstSearch dijkstra = (BestFirstSearch) feeder.getDijkstra();
for (Problem problem : problems){
//使用AStar引擎求解问题
Deque<Node> path = dijkstra.search(problem);
//解的可视化
problem.showSolution(path);
//仅打印路径
problem.printPath(path);
System.out.println(dijkstra.expandedNode());
System.out.println();
}*/
}
}

@ -0,0 +1,149 @@
package core.solver;
import core.problem.Action;
import core.problem.State;
import core.solver.heuristic.EvaluationType;
import core.solver.heuristic.Predictor;
import java.util.Comparator;
import java.util.EnumMap;
import static core.solver.heuristic.EvaluationType.*;
public final class Node{
//不考虑路径代价的Node
/**
*
* @param state
* @param parent
* @param action Action
*/
public Node(State state, Node parent, Action action){
this(state, parent, action, 0, 0);
}
//考虑路径代价的Node
/**
*
* @param state
* @param parent
* @param action Action
* @param pathCost
* @param heuristic
*/
public Node(State state, Node parent, Action action, int pathCost, int heuristic) {
super();
this.state = state;
this.parent = parent;
this.action = action;
this.pathCost = pathCost;
this.heuristic = heuristic;
}
/**
*
* @param action使Action
* @param predictorh
* @param goal: h
* @return
*/
public Node childNode(Action action, Predictor predictor, State goal) {
return new Node(state.next(action), this, action,
pathCost + action.stepCost(),
predictor.heuristics(state, goal));
}
private final State state; // the state in the state space to which the node corresponds
private final Node parent; // the node in the search tree which generated this node
public Action getAction() {
return action;
}
private final Action action; // the action that was applied to the parent to generate the node
private final int pathCost; // the cost of the path from the initial state to this node
private final int heuristic; // estimated cost of the cheapest path from the state of this node to a goal state
//返回当前Node的f值 f = g + h
public int evaluation()
{
return pathCost + heuristic;
}
public State getState() {
return state;
}
public Node getParent() {
return parent;
}
public int getPathCost() {
return pathCost;
}
public int getHeuristic() {
return heuristic;
}
/**
* Node
*/
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj instanceof Node) {
Node another = (Node) obj;
//两个Node对象的状态相同则认为是相同的
return this.getState().equals(another.getState());
}
return false;
//Node another = (Node) obj;
//return obj == this || this.getState().equals(another.getState());
}
public void draw() {
System.out.println(this);
}
/**
*
*/
private static final EnumMap<EvaluationType, Comparator<Node>> evaluators = new EnumMap<>(EvaluationType.class);
//枚举映射表的初始化
static{
//f = g + h FULL
evaluators.put(FULL,
Comparator.comparingInt(Node::evaluation)
);
//g PATH_COST
evaluators.put(PATH_COST,
Comparator.comparingInt(Node::getPathCost)
);
//h HEURISTIC
evaluators.put(HEURISTIC,
Comparator.comparingInt(Node::getHeuristic)
);
}
/**
*
* @param type
* @return
*/
public static Comparator<Node> evaluator(EvaluationType type) {
return evaluators.get(type);
}
@Override
public String toString() {
return "[" + state.toString() + "⬅" + "[" + parent.getState().toString() + ", " + action.toString() + "], " + pathCost + ", " + heuristic + "]";
}
}

@ -0,0 +1,29 @@
package core.solver;
import core.problem.Problem;
import java.util.ArrayDeque;
import java.util.Deque;
public interface Searcher {
/**
* @problem
* @return null
*/
Deque<Node> search(Problem problem);
/**
*
* @param node
* @return
*/
default Deque<Node> generatePath(Node node) {
Deque<Node> stack = new ArrayDeque<>();
while (node.getParent() != null) {
stack.push(node);
node = node.getParent();
}
return stack;
}
}

@ -0,0 +1,4 @@
package core.solver.blinded;
public class BreadthFirstSearch {
}

@ -0,0 +1,4 @@
package core.solver.blinded;
public class DepthFirstSearch {
}

@ -0,0 +1,70 @@
package core.solver.heuristic;
import core.problem.State;
import core.solver.Node;
import java.util.*;
/**
* AbstractQueue
* core.solver.Node
*/
public abstract class AbstractFrontier extends AbstractQueue<Node> {
public AbstractFrontier(Comparator<Node> evaluator) {
this.evaluator = evaluator;
}
public Comparator<Node> getEvaluator() {
return evaluator;
}
// 节点优先级比较器在Node类中定义了三个不同的比较器Dijkstra, Greedy Best-First, and Best-First
// 不同的选择对应不同的算法。
protected final Comparator<Node> evaluator;
/**
* Frontier s
* @param s
* @return s
* null
*/
protected abstract Node getNode(State s);
/**
* Frontiernode
*
* @param node
* @return true
*/
public final boolean discardOrReplace(Node node){
if (node == null)
throw new NullPointerException();
//结点node是否出现在frontier中; null: not revisited
Node oldNode = getNode(node.getState());
//如果oldNode为null则当前结点node的状态不在Frontier中那么肯定在explored表中
// 又因为h函数是consistent的所以discard
//如果oldNode不为null则在oldNode已经在Frontier中并且旧的估值比新的大即新生成的结点更好
if (oldNode != null && evaluator.compare(oldNode, node) > 0){
//则,用新节点替换旧节点
replace(oldNode, node);
}
return true;
}
/**
* e oldNode
*
* @param oldNode
* @param newNode
*/
public void replace(Node oldNode, Node newNode) {
this.remove(oldNode);
this.add(newNode);
}
public boolean contains(Node node) {
return false;
}
}

@ -0,0 +1,77 @@
package core.solver.heuristic;
import java.util.*;
import core.problem.Problem;
import core.problem.State;
import core.solver.*;
import g04.problem.npuzzle.PuzzleState;
/**
* final
*/
public final class BestFirstSearch implements Searcher {
//已经访问过的节点集合
private final Set<State> explored;
//还未扩展的节点队列
private final AbstractFrontier frontier;
private final Predictor predictor;
/**
*
* @param explored Set hashSet
* @param frontier Nodefrontier
*/
public BestFirstSearch(Set<State> explored, AbstractFrontier frontier, Predictor predictor) {
this.explored = explored;
this.frontier = frontier;
this.predictor = predictor;
}
@Override
public Deque<Node> search(Problem problem)
{
//如果可直接判断问题是否可解无解时直接返回解路径为null
if (!problem.solvable()){
return null;
}
frontier.clear();
explored.clear();
//搜索树的根节点
Node root = problem.root(predictor);
this.frontier.add(root);
//int i = 0;
while (true) {
if (frontier.isEmpty())
return null; //失败
Node node = frontier.poll(); //choose the lowest-cost node in frontier
//如果已经到达目标状态,
if (problem.goal(node.getState())) {
return generatePath(node);
}
//将当前结点放入explored表中
explored.add(node.getState());
//System.out.println(i++);
for (Node child : problem.childNodes(node, predictor)) {
// 如果新扩展的节点没有在Explored和Fringe中出现过。
// 因为两个node的状态相同则视为二者相同equals函数
// 所以contains函数判断frontier中是否存在跟child的状态相同的结点
if (!explored.contains(child.getState()) && !frontier.contains(child)) {
frontier.offer(child);
}
else {
//child出现在Explored或Fringe中
//在启发函数满足单调条件的前提下如果child是出现在Explored表里的节点肯定不在Fringe中
//而且到达这个节点的新路径肯定不会比旧路径更优
frontier.discardOrReplace(child);
}
}
}
}
public int expandedNode(){
return explored.size();
}
}

@ -0,0 +1,11 @@
package core.solver.heuristic;
/**
* Best-First
*
*/
public enum EvaluationType {
FULL,
PATH_COST,
HEURISTIC //对于不同的问题,启发策略又可能又多种。
}

@ -0,0 +1,18 @@
package core.solver.heuristic;
import core.problem.State;
/**
*
*
*/
public interface Predictor {
/**
*
* @param
* state
* goal
* @return
*/
int heuristics(State state, State goal);
}

@ -0,0 +1,84 @@
package g04.problem.npuzzle;
import algs4.util.In;
import core.problem.Problem;
import core.runner.EngineFeeder;
import core.runner.HeuristicType;
import core.solver.Node;
import core.solver.Searcher;
import core.solver.heuristic.AbstractFrontier;
import core.solver.heuristic.EvaluationType;
import core.solver.heuristic.Predictor;
import g04.solver.heuristic.IDAStarSearch;
import g04.solver.heuristic.MyFrontier;
import java.util.ArrayList;
import java.util.Scanner;
public class MyFeeder extends EngineFeeder {
/**
* NPuzzle
* @param io
* @return NPuzzle
*/
@Override
public ArrayList<Problem> getProblems(In io) {
ArrayList<Problem> problems = new ArrayList<Problem>();
while (io.hasNextLine()){
//棋盘大小
int size = io.readInt();
int[][] board = new int[size][size];
//读入初始状态
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
board[i][j] = io.readInt();
PuzzleState initState = new PuzzleState(board, size);
//读入目标状态
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
board[i][j] = io.readInt();
PuzzleState goal = new PuzzleState(board, size);
Puzzle puzzleProblem = new Puzzle(initState, goal, size);
//添加到问题列表
problems.add(puzzleProblem);
}
return problems;
}
@Override
public ArrayList<Problem> getProblems(Scanner scanner) {
return null;
}
@Override
public AbstractFrontier getFrontier(EvaluationType type) {
return new MyFrontier(Node.evaluator(type));
}
/**
*
* @param type
* @return
*/
@Override
public Predictor getPredictor(HeuristicType type) {
return PuzzleState.predictor(type);
}
/**
* IDA*
* @return IDA*
*/
@Override
public Searcher getIdaStar() {
return new IDAStarSearch(PuzzleState.predictor(HeuristicType.MANHATTAN));
}
/**
* @return A*
*/
@Override
public Searcher getScoreSearcher() {
return getAStar(HeuristicType.MANHATTAN);
}
}

@ -0,0 +1,155 @@
package g04.problem.npuzzle;
import core.problem.Action;
import core.problem.Problem;
import core.problem.State;
import core.solver.Node;
import core.solver.heuristic.Predictor;
import java.util.ArrayList;
import java.util.Deque;
import java.util.Random;
public class Puzzle extends Problem {
//Zobrist哈希随机值
public static int[][][] Zobrist;
//目标状态到默认状态的曼哈顿距离(默认状态为按顺序放置位将牌,空格最后)
public static int[][][] goalmanhattan;
/**
*
* @param initialState
* @param goal
* @param size
*/
public Puzzle(State initialState, State goal, int size) {
super(initialState, goal, size);
Random r = new Random();
goalmanhattan = new int[size][size][2];
Zobrist = new int[size][size][size * size];
for(int i = 0; i < size; i++) {
for(int j = 0; j < size; j++) {
goalmanhattan[i][j][0] = (((PuzzleState)goal).getBoardAt(i, j) - 1) / size;;
goalmanhattan[i][j][1] = (((PuzzleState)goal).getBoardAt(i, j) - 1) % size;;;
for(int k = 0; k < size * size; k++) {
Zobrist[i][j][k] = r.nextInt();
}
}
}
}
/**
*
* @param i
* @param j
* @param state
* @return Zobrist
*/
public static int getZobristAt(int i, int j, int state) {
return Zobrist[i][j][state];
}
/**
*
* @return
*/
@Override
public boolean solvable() {
return ((PuzzleState)initialState).parity() == ((PuzzleState)goal).parity();
}
@Override
public int stepCost(State state, Action action) {
return 1;
}
/**
*
* @param state
* @param action
* @return actiontrue: false:
*/
@Override
protected boolean applicable(State state, Action action) {
//获取action对应的位移量
int[] next = ((PuzzleAction)action).getNext();
//空白位移动后是否越界
int row = ((PuzzleState)state).getBlank(0) + next[0];
int col = ((PuzzleState)state).getBlank(1) + next[1];
return row >= 0 && row < size && col >= 0 && col < size;
}
@Override
public void showSolution(Deque<Node> path) {
}
/**
*
*/
@Override
public void draw() {
initialState.draw();
System.out.println();
goal.draw();
}
/**
*
* @param path
*/
@Override
public void printPath(Deque<Node> path) {
if (path == null){
System.out.println("No Solution.");
return;
}
initialState.draw();
for (Node node : path) {
PuzzleAction puzzleAction = (PuzzleAction) node.getAction();
puzzleAction.draw();
PuzzleState puzzleState = (PuzzleState) node.getState();
puzzleState.draw();
}
System.out.println();
}
public final Iterable<? extends Node> childs(Node parent) {
ArrayList<Node> nodes = new ArrayList<>();
//父结点的状态
State parentState = parent.getState();
//对于parentState上所有可能的action但有的不可行
//parentState.draw();
for (Action action : parentState.actions()){
//如果父结点状态下的动作是可行的
if (applicable(parentState, action)){
//得到后继状态
State state = parentState.next(action);
//计算路径长度 = 父结点路径长度 + 进入后继状态所采取的动作的代价
int pathCost = parent.getPathCost() + stepCost(state, action);
//根据曼哈顿距离特性,只需要计算被移动的位将牌改变的曼哈顿距离
int heuristics = parent.getHeuristic() - nextManhattan((PuzzleState)parentState, (PuzzleState)state);
//生成子结点
Node child = new Node(state, parent, action, pathCost, heuristics);
nodes.add(child);
}
}
return nodes;
}
/**
*
* @param parent
* @param child
* @return
*/
public int nextManhattan(PuzzleState parent, PuzzleState child) {
//被移动的位将牌对应数字
int n = parent.getBoardAt(child.getBlank(0), child.getBlank(1));
int x = (n - 1) / size;
int y = (n - 1) % size;
return Math.abs(goalmanhattan[x][y][0] - child.getBlank(0)) + Math.abs(goalmanhattan[x][y][1] - child.getBlank(1))
- Math.abs(goalmanhattan[x][y][0] - parent.getBlank(0)) - Math.abs(goalmanhattan[x][y][1] - parent.getBlank(1));
}
}

@ -0,0 +1,40 @@
package g04.problem.npuzzle;
import core.problem.Action;
public class PuzzleAction extends Action {
/*
*
* 0: Up, 1: Right, 2: Down, 3: Right
*/
private final int dir;
// 移动方向
private static final char[] direction = {'R', 'D', 'L', 'U'};
private static final int[][] next = {
{0, 1}, {1, 0}, {0, -1}, {-1, 0}
};
public PuzzleAction(int dir) {
this.dir = dir;
}
public int[] getNext() {
return next[dir];
}
/**
* action
*/
@Override
public void draw() {
System.out.println(" ↓");
System.out.println(" ↓-(#, " + direction[dir] + ")");
System.out.println(" ↓");
}
@Override
public int stepCost() {
return 1;
}
}

@ -0,0 +1,252 @@
/**
*
*/
package g04.problem.npuzzle;
import core.problem.Action;
import core.problem.State;
import core.runner.HeuristicType;
import core.solver.heuristic.Predictor;
import xu.problem.pathfinding.Direction;
import xu.problem.pathfinding.Move;
import xu.problem.pathfinding.Position;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.Objects;
import java.util.Scanner;
/**
*
* wanwenlong
* 2021328
*
*
*
* 1.0.0
*/
public class PuzzleState extends State {
private final int size;
//该状态每个位置的位将牌数字
private final int[][] board;
//空格对应位置
private int[] blank;
/**
*
*/
public PuzzleState(int[][] board, int size) {
this.size = size;
this.board = new int[size][size];
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
this.board[i][j] = board[i][j];
if (board[i][j] == 0)
this.blank = new int[]{i, j};
}
}
}
/**
*
*/
public PuzzleState(PuzzleState puzzleState) {
this.size = puzzleState.size;
this.board = new int[size][size];
for (int i = 0; i < size; i++) {
System.arraycopy(puzzleState.board[i], 0, this.board[i], 0, size);
}
this.blank = new int[]{puzzleState.blank[0], puzzleState.blank[1]};
}
public int getSize() {
return size;
}
public int getBoardAt(int i, int j) {
return board[i][j];
}
public int getBoardAt(int i) {
return board[i/size][i%size];
}
public int getBlank(int i) {
return blank[i];
}
/**
*
*/
@Override
public void draw() {
drawLine();
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
System.out.print("| " + String.valueOf(board[i][j]) + " ");
}
System.out.println("|");
drawLine();
}
}
/**
* 线
*/
public void drawLine() {
for (int i = 0; i < size; i++)
System.out.print("+---");
System.out.println("+");
}
/**
* action
* @param action
* @return
*/
@Override
public State next(Action action) {
PuzzleState nextState = new PuzzleState(this);
int[] next = ((PuzzleAction)action).getNext();
nextState.blank[0] += next[0];
nextState.blank[1] += next[1];
nextState.board[this.blank[0]][this.blank[1]] = this.board[nextState.blank[0]][nextState.blank[1]];
nextState.board[nextState.blank[0]][nextState.blank[1]] = 0;
return nextState;
}
/**
* Action
* @return Action
*/
@Override
public Iterable<? extends Action> actions() {
ArrayList<Action> actions = new ArrayList<Action>();
for (int d = 0; d < 4; d++)
actions.add(new PuzzleAction(d));
return actions;
}
/**
* NPuzzle
* @return 1: 0:
*/
public int parity() {
int n = (size % 2 == 0) ? blank[0] + 1 : 0;
for (int i = 0; i < size * size; i++) {
for (int j = 0; j < i; j++) {
if (this.getBoardAt(i) != 0 && this.getBoardAt(j) != 0 && this.getBoardAt(i) < this.getBoardAt(j))
n++;
}
}
return n % 2;
}
@Override
public boolean equals(Object obj) {
for (int i = 0; i < size * size - 1; i++) {
if (this.getBoardAt(i) != ((PuzzleState) obj).getBoardAt(i))
return false;
}
return true;
//return this.hashCode() == obj.hashCode();
}
/**
* Zobrist
* @return
*/
@Override
public int hashCode() {
int hash = 0;
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
hash ^= Puzzle.getZobristAt(i, j, board[i][j]);
}
}
return hash;
}
//枚举映射,存放不同类型的启发函数
private static final EnumMap<HeuristicType, Predictor> predictors = new EnumMap<>(HeuristicType.class);
static{
predictors.put(HeuristicType.MISPLACED,
(state, goal) -> ((PuzzleState)state).misPlaced((PuzzleState)goal));
predictors.put(HeuristicType.MANHATTAN,
(state, goal) -> ((PuzzleState)state).manhattan((PuzzleState)goal));
predictors.put(HeuristicType.DISJOINT_PATTERN,
(state, goal) -> ((PuzzleState)state).disjointPattern((PuzzleState)goal));
}
public static Predictor predictor(HeuristicType type){
return predictors.get(type);
}
/**
*
*/
private int misPlaced(PuzzleState goal) {
int heuristics = 0;
int size = goal.getSize();
for (int i = 0; i < size * size - 1; i++) {
if (this.getBoardAt(i) != 0 && this.getBoardAt(i) != goal.getBoardAt(i))
heuristics++;
}
return heuristics;
}
/**
*
*/
private int manhattan(PuzzleState goal) {
int heuristics = 0;
int[][][] m = new int[size][size][2];
int x, y;
//第一步,计算当前状态到默认状态曼哈顿距离
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (this.board[i][j] == 0)
continue;
x = (this.board[i][j] - 1) / size;
y = (this.board[i][j] - 1) % size;
m[x][y][0] = x - i;
m[x][y][1] = y - j;
}
}
//第二步,计算默认状态到目标状态曼哈顿距离
//结合两步即为当前状态到目标状态曼哈顿距离
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (goal.board[i][j] == 0)
continue;
x = (goal.board[i][j] - 1) / size;
y = (goal.board[i][j] - 1) % size;
heuristics += Math.abs(m[x][y][0] + i - x) + Math.abs(m[x][y][1] + j - y);
}
}
return heuristics;
}
/**
* Disjoint pattern heuristic
*/
private int disjointPattern(PuzzleState goal) {
return 0;
}
public static void main(String[] args) {
int[][] a = new int[][]{{8, 13, 0, 6}, {1, 15, 9, 14}, {3, 4, 5, 11}, {7, 2, 10, 12}};
int[][] g = new int[][]{{1, 2, 3}, {4, 5, 6}, {7, 8, 0}};
PuzzleState puzzleState = new PuzzleState(a, 4);
int n = 0;
for (int i = 0; i < 4 * 4; i++) {
for (int j = 0; j < i; j++) {
if (puzzleState.getBoardAt(i) != 0 && puzzleState.getBoardAt(j) != 0 && puzzleState.getBoardAt(i) < puzzleState.getBoardAt(j))
n++;
}
System.out.println(n);
}
System.out.println(n);
}
}

@ -0,0 +1,65 @@
package g04.solver.heuristic;
import core.problem.Problem;
import core.solver.Node;
import core.solver.Searcher;
import core.solver.heuristic.Predictor;
import g04.problem.npuzzle.Puzzle;
import java.util.Deque;
import java.util.Stack;
public class IDAStarSearch implements Searcher {
private final Predictor predictor;
//裁剪阈值
private int cutoff;
//下一轮迭代的裁剪阈值
private int newCutoff;
//最大迭代深度
private int maxIteratorDepth = 256;
private final Stack<Node> openStack;
private final Stack<Node> closeStack;
public IDAStarSearch(Predictor predictor) {
this.predictor = predictor;
openStack = new Stack<Node>();
closeStack = new Stack<Node>();
}
@Override
public Deque<Node> search(Problem problem) {
//获取根节点
openStack.clear();
Node root = problem.root(predictor);
cutoff = root.evaluation();
while (cutoff < maxIteratorDepth) {
openStack.push(root);
newCutoff = cutoff;
//当栈未空时继续,执行带裁剪值的深度优先搜索
while (!openStack.empty()) {
Node node = openStack.pop();
//更新裁剪值为未被探索节点中最小的评估值
newCutoff = (newCutoff > cutoff) ? (Math.min(node.evaluation(), newCutoff)) : node.evaluation();
if (problem.goal(node.getState())) {
return generatePath(node);
}
//当小于等于裁剪值时,继续向深处搜索
if (node.evaluation() <= cutoff) {
for (Node child : ((Puzzle)problem).childs(node)) {
//剪枝,防止节点探索回到父节点
if (node.getParent() == null || !node.getParent().equals(child)) {
openStack.push(child);
}
}
}
}
//更新裁剪值
cutoff = newCutoff;
//System.out.println(cutoff);
}
return null;
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save