Skip to content

Commit

Permalink
- Added new package StringUtil for string utility functions.
Browse files Browse the repository at this point in the history
- Improved Util.stringWrap and renamed it StringUtil.wordWrap.


git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@24303 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
perost committed Jan 29, 2015
1 parent 109ae13 commit b68318f
Show file tree
Hide file tree
Showing 4 changed files with 283 additions and 98 deletions.
24 changes: 13 additions & 11 deletions Compiler/Util/Flags.mo
Expand Up @@ -56,15 +56,17 @@ encapsulated package Flags
depending on which type it is.
"

public import Util;

protected import Corba;
protected import Error;
protected import ErrorExt;
protected import Global;
protected import List;
protected import Print;
protected import Settings;
protected import StringUtil;
protected import System;
public import Util;

public uniontype DebugFlag
record DEBUG_FLAG
Expand Down Expand Up @@ -1926,16 +1928,16 @@ algorithm
case {"optmodules"}
equation
str1 = System.gettext("The --preOptModules flag sets the optimization modules which are used before the\nmatching and index reduction in the back end. These modules are specified as a comma-separated list, where the valid modules are:");
str1 = stringAppendList(Util.stringWrap(str1,System.getTerminalWidth(),"\n"));
str1 = stringAppendList(StringUtil.wordWrap(str1,System.getTerminalWidth(),"\n"));
str2 = printFlagValidOptionsDesc(PRE_OPT_MODULES);
str3 = System.gettext("The --matchingAlgorithm sets the method that is used for the matching algorithm, after the pre optimization modules. Valid options are:");
str3 = stringAppendList(Util.stringWrap(str3,System.getTerminalWidth(),"\n"));
str3 = stringAppendList(StringUtil.wordWrap(str3,System.getTerminalWidth(),"\n"));
str4 = printFlagValidOptionsDesc(MATCHING_ALGORITHM);
str5 = System.gettext("The --indexReductionMethod sets the method that is used for the index reduction, after the pre optimization modules. Valid options are:");
str5 = stringAppendList(Util.stringWrap(str5,System.getTerminalWidth(),"\n"));
str5 = stringAppendList(StringUtil.wordWrap(str5,System.getTerminalWidth(),"\n"));
str6 = printFlagValidOptionsDesc(INDEX_REDUCTION_METHOD);
str7 = System.gettext("The --postOptModules then sets the optimization modules which are used after the index reduction, specified as a comma-separated list. The valid modules are:");
str7 = stringAppendList(Util.stringWrap(str7,System.getTerminalWidth(),"\n"));
str7 = stringAppendList(StringUtil.wordWrap(str7,System.getTerminalWidth(),"\n"));
str8 = printFlagValidOptionsDesc(POST_OPT_MODULES);
help = stringAppendList({str1,"\n\n",str2,"\n",str3,"\n\n",str4,"\n",str5,"\n\n",str6,"\n",str7,"\n\n",str8,"\n"});
then help;
Expand All @@ -1944,7 +1946,7 @@ algorithm
equation
(config_flag as CONFIG_FLAG(name=name,description=desc)) = List.getMemberOnTrue(str, allConfigFlags, matchConfigFlag);
str1 = "-" + name;
str2 = stringAppendList(Util.stringWrap(Util.translateContent(desc), System.getTerminalWidth(), "\n"));
str2 = stringAppendList(StringUtil.wordWrap(Util.translateContent(desc), System.getTerminalWidth(), "\n"));
str = printFlagValidOptionsDesc(config_flag);
help = stringAppendList({str1,"\n",str2,"\n",str});
then help;
Expand Down Expand Up @@ -2012,7 +2014,7 @@ protected
algorithm
(str1,str2) := topic;
str1 := Util.stringPadRight(str1,13," ");
str := stringAppendList(Util.stringWrap(str1 + str2, System.getTerminalWidth(), "\n "));
str := stringAppendList(StringUtil.wordWrap(str1 + str2, System.getTerminalWidth(), "\n "));
end makeTopicString;

public function printUsage
Expand Down Expand Up @@ -2074,7 +2076,7 @@ algorithm
name = Util.stringPadRight(printConfigFlagName(inFlag), 28, " ");
flag_str = stringAppendList({name, " ", desc_str});
delim_str = descriptionIndent + " ";
wrapped_str = Util.stringWrap(flag_str, System.getTerminalWidth(), delim_str);
wrapped_str = StringUtil.wordWrap(flag_str, System.getTerminalWidth(), delim_str);
opt_str = printValidOptions(inFlag);
flag_str = stringDelimitList(wrapped_str, "\n") + opt_str + "\n";
then
Expand Down Expand Up @@ -2120,7 +2122,7 @@ algorithm
equation
opt_str = descriptionIndent + " " + System.gettext("Valid options:") + " " +
stringDelimitList(strl, ", ");
strl = Util.stringWrap(opt_str, System.getTerminalWidth(), descriptionIndent + " ");
strl = StringUtil.wordWrap(opt_str, System.getTerminalWidth(), descriptionIndent + " ");
opt_str = stringDelimitList(strl, "\n");
opt_str = "\n" + opt_str;
then
Expand Down Expand Up @@ -2169,7 +2171,7 @@ algorithm
desc_str := Util.translateContent(desc);
str := Util.stringPadRight(" * " + name + " ", 30, " ") + desc_str;
outString := stringDelimitList(
Util.stringWrap(str, System.getTerminalWidth(), descriptionIndent + " "), "\n") + "\n";
StringUtil.wordWrap(str, System.getTerminalWidth(), descriptionIndent + " "), "\n") + "\n";
end printFlagOptionDesc;

protected function printDebugFlag
Expand All @@ -2184,7 +2186,7 @@ algorithm
DEBUG_FLAG(default = default, name = name, description = desc) := inFlag;
desc_str := Util.translateContent(desc);
outString := Util.stringPadRight((if default then " + " else " - ") + name + " ", 26, " ") + desc_str;
outString := stringDelimitList(Util.stringWrap(outString, System.getTerminalWidth(),
outString := stringDelimitList(StringUtil.wordWrap(outString, System.getTerminalWidth(),
descriptionIndent), "\n") + "\n";
end printDebugFlag;

Expand Down
269 changes: 269 additions & 0 deletions Compiler/Util/StringUtil.mo
@@ -0,0 +1,269 @@
/*
* This file is part of OpenModelica.
*
* Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC),
* c/o Linköpings universitet, Department of Computer and Information Science,
* SE-58183 Linköping, Sweden.
*
* All rights reserved.
*
* THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR
* THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2.
* ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
* RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3,
* ACCORDING TO RECIPIENTS CHOICE.
*
* The OpenModelica software and the Open Source Modelica
* Consortium (OSMC) Public License (OSMC-PL) are obtained
* from OSMC, either from the above address,
* from the URLs: http://www.ida.liu.se/projects/OpenModelica or
* http://www.openmodelica.org, and in the OpenModelica distribution.
* GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html.
*
* This program is distributed WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
* IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
*
* See the full OSMC Public License conditions for more details.
*
*/

encapsulated package StringUtil
" file: StringUtil.mo
package: StringUtil
description: String utility functions.

RCS: $Id$

This package contains various utility functions for handling the builtin
MetaModelica String type."

protected import System;

protected import MetaModelica.Dangerous.{listReverseInPlace, stringGetNoBoundsChecking};

public constant Integer NO_POS := 0;
protected constant Integer CHAR_SPACE = 32;
protected constant Integer CHAR_DASH = 45;

public function findChar
"Searches for a given character in the given string, returning the index of
the character if found. If not found returns NO_POS. The start and end
position determines the section of the string to search in, and if not
specified they are set to the start and end of the string."
input String inString;
input Integer inChar;
input Integer inStartPos := 1;
input Integer inEndPos := 0;
output Integer outIndex := NO_POS;
protected
constant Integer len := stringLength(inString);
Integer start_pos, end_pos;
algorithm
start_pos := max(inStartPos, 1);
end_pos := if inEndPos > 0 then min(inEndPos, len) else len;

for i in start_pos:end_pos loop
if stringGetNoBoundsChecking(inString, i) == inChar then
outIndex := i;
break;
end if;
end for;
end findChar;

public function rfindChar
"Searches backwards for a given character in the given string, returning the
index of the character if found. If not found returns NO_POS. The start and
end position determines the section of the string to search in, and if not
specified they are set to the start and end of the string."
input String inString;
input Integer inChar;
input Integer inStartPos := 0;
input Integer inEndPos := 1;
output Integer outIndex := NO_POS;
protected
constant Integer len := stringLength(inString);
Integer start_pos, end_pos;
algorithm
start_pos := if inStartPos > 0 then min(inStartPos, len) else len;
end_pos := max(inEndPos, 1);

for i in start_pos:-1:end_pos loop
if stringGetNoBoundsChecking(inString, i) == inChar then
outIndex := i;
break;
end if;
end for;
end rfindChar;

public function findCharNot
"Searches for a character not matching the given character in the given
string, returning the index of the character if found. If not found returns
NO_POS. The start and end position determines the section of the string to
search in, and if not specified they are set to the start and end of the
string."
input String inString;
input Integer inChar;
input Integer inStartPos := 1;
input Integer inEndPos := 0;
output Integer outIndex := NO_POS;
protected
constant Integer len := stringLength(inString);
Integer start_pos, end_pos;
algorithm
start_pos := max(inStartPos, 1);
end_pos := if inEndPos > 0 then min(inEndPos, len) else len;

for i in start_pos:end_pos loop
if stringGetNoBoundsChecking(inString, i) <> inChar then
outIndex := i;
break;
end if;
end for;
end findCharNot;

public function rfindCharNot
"Searches backwards for a character not matching the given character in the
given string, returning the index of the character if found. If not found
returns NO_POS. The start and end position determines the section of the
string to search in, and if not specified they are set to the start and end
of the string."
input String inString;
input Integer inChar;
input Integer inStartPos := 0;
input Integer inEndPos := 1;
output Integer outIndex := NO_POS;
protected
constant Integer len := stringLength(inString);
Integer start_pos, end_pos;
algorithm
start_pos := if inStartPos > 0 then min(inStartPos, len) else len;
end_pos := max(inEndPos, 1);

for i in start_pos:-1:end_pos loop
if stringGetNoBoundsChecking(inString, i) <> inChar then
outIndex := i;
break;
end if;
end for;
end rfindCharNot;

public function isAlpha
"Returns true if the given character represented by it's ASCII decimal number
is an alphabetic character."
input Integer inChar;
output Boolean outIsAlpha := (inChar >= 65 and inChar <= 90) or
(inChar >= 97 and inChar <= 122);
end isAlpha;

public function wordWrap
"Breaks the given string into lines which are no longer than the given wrap
length. The function tries to break lines at word boundaries, i.e. at spaces,
so that words are not split. It also wraps the string at any newline
characters it finds. The function also takes two optional parameters to set
the delimiter and raggedness.
inDelimiter sets the delimiter which is prefixed to all lines except for the
first one. The length of this delimiter is taken into account when wrapping
the string, so it must be shorter than the wrap length. Otherwise the string
will be returned unwrapped. The default is an empty string.
inRaggedness determines the allowed raggedness of the lines, given as a ratio
between 0 and 1. A raggedness of e.g. 0.2 means that each segment may be at
most 20% smaller than the max line length. If a line would be shorter than
this, due to a long word, then the function instead hyphenates the last word.
This is not done according to any grammatical rules, the words are just
broken so that the line is as long as allowed. The default is 0.3.
This function operates on ASCII strings, and does not handle UTF-8 strings
correctly."
input String inString;
input Integer inWrapLength;
input String inDelimiter := "";
input Real inRaggedness := 0.3;
output list<String> outStrings := {};
protected
Integer start_pos := 1, end_pos := inWrapLength;
Integer line_len, pos, next_char, char, gap_size, next_gap_size;
String str, delim := "";
list<String> lines;
algorithm
// Check that the wrap length is larger than the delimiter, otherwise just
// return the string as it is.
if stringLength(inDelimiter) >= inWrapLength - 1 then
outStrings := {inString};
return;
end if;

// Split the string at newlines.
lines := System.strtok(inString, "\n");
// Calculate the length of each line, excluding the delimiter.
line_len := inWrapLength - stringLength(inDelimiter) - 1;
// The gap size is how many characters a line may be shorter than the sought
// after line length.
gap_size := max(realInt(realMul(line_len, inRaggedness)), 0);

// Wrap each line separately.
for line in lines loop
while end_pos < stringLength(line) loop
next_char := stringGetNoBoundsChecking(line, end_pos + 1);

if next_char <> CHAR_SPACE and next_char <> CHAR_DASH then
// If the next character isn't a space or dash, search backwards for a space.
pos := rfindChar(line, CHAR_SPACE, end_pos, end_pos - gap_size);

if pos <> NO_POS then
// A space was found, break the string here.
str := substring(line, start_pos, pos - 1);
start_pos := pos + 1;
else
// No space was found, search for a dash instead.
pos := rfindChar(line, CHAR_DASH, end_pos, start_pos + gap_size);

if pos > 1 then
// A dash was found, check that the previous character is alphabetic.
char := stringGetNoBoundsChecking(line, pos - 1);
pos := if isAlpha(char) and isAlpha(next_char) then pos else NO_POS;
end if;

if pos <> NO_POS then
// A dash was found, break the string here.
str := substring(line, start_pos, pos);
start_pos := pos + 1;
else
// No dash was found, break the word and hyphenate it.
str := substring(line, start_pos, end_pos - 1) + "-";
start_pos := end_pos;
end if;
end if;
else
// The next character is a space or dash, split the string here.
str := substring(line, start_pos, end_pos);
// Skip the space.
start_pos := end_pos + (if next_char == CHAR_SPACE then 2 else 1);
end if;

// Add the string to the list and continue with the rest of the line.
outStrings := (delim + str) :: outStrings;
end_pos := start_pos + line_len;
delim := inDelimiter;
end while;

// Add any remainder of the line to the list.
if start_pos < stringLength(line) then
str := delim + substring(line, start_pos, stringLength(line));
outStrings := str :: outStrings;
end if;

// Continue with the next line.
start_pos := 1;
end_pos := line_len;
delim := inDelimiter;
end for;

outStrings := listReverseInPlace(outStrings);
end wordWrap;

annotation(__OpenModelica_Interface="util");
end StringUtil;

0 comments on commit b68318f

Please sign in to comment.