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
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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 */
|
File diff suppressed because it is too large
Load Diff
@ -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_ */
|
File diff suppressed because it is too large
Load Diff
@ -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 */
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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} ≤ {@code p} ≤ {@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 μ
|
||||
* and standard deviation σ.
|
||||
*
|
||||
* @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 λ.
|
||||
*
|
||||
* @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 α.
|
||||
*
|
||||
* @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 λ.
|
||||
*
|
||||
* @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,8 @@
|
||||
package core.runner;
|
||||
|
||||
public enum ProblemType {
|
||||
NPUZZLE, // NPuzzle问题
|
||||
PATHFINDING, // 寻路问题
|
||||
SLIDING_BLOCKS, // 滑动积木块问题
|
||||
MISSIONARY_AND_CARNIVAL //野人传教士问题
|
||||
}
|
@ -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,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,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,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…
Reference in new issue