Skip to content

Commit

Permalink
Merge pull request #12 from jbante/master
Browse files Browse the repository at this point in the history
Fixes for handling newline characters
  • Loading branch information
dansmith65 committed Jan 1, 2014
2 parents 174e6ce + e2a1c05 commit c3ccf0b
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 150 deletions.
7 changes: 5 additions & 2 deletions Functions/#Name-Value/#.fmfn
Expand Up @@ -16,6 +16,9 @@
* DEPENDENCIES: none
*
* HISTORY:
* MODIFIED on 2013-12-24 by Jeremy Bante <http://scr.im/jbante> to return
* an error if name contains a carriage return (Char ( 13 )), and removing
* explicit encoding for line feeds.
* MODIFIED on 2013-12-12 by John Jones <john.christopher@alumni.virginia.edu>
* to explicitly encode line feed characters in text values.
* MODIFIED on 2013-09-02 by Daniel Smith dansmith65@gmail.com to fix a
Expand Down Expand Up @@ -72,7 +75,7 @@ Let ( [
"GetAsDate ( " & Quote ( value ) & " )" ;

~text ≠ GetAsText ( ~number ) ;
Substitute ( Quote ( value ) ; Char ( 10 ) ; "\" & Char ( 10 ) & \"" ) ;
Quote ( value ) ;

/* Else */
~number
Expand All @@ -89,7 +92,7 @@ Let ( [
& " ~ = \"\" ]; \"\" )" ;
~error =
Case (
IsEmpty ( ~name ) ;
IsEmpty ( ~name ) or Position ( ~name ; ¶ ; 1 ; 1 ) ≠ 0 ;
11 ; // Name is not valid

not IsValidExpression ( ~testExpression ) ;
Expand Down
72 changes: 31 additions & 41 deletions Functions/#Name-Value/#Filter.fmfn
Expand Up @@ -23,7 +23,9 @@
* DEPENDENCIES: none
*
* HISTORY:
* MODIFIED on 2013-12-23 by John Jones john.christopher@alumni.virginia.edu
* MODIFIED on 2013-12-24 by Jeremy Bante <http://scr.im/jbante> to improve
* efficiency.
* MODIFIED on 2013-12-23 by John Jones <john.christopher@alumni.virginia.edu>
* to use Position/Middle. Modified to add trailing return if it doesn't
* exist.
* CREATED on 2012-11-28 by Jeremy Bante <http://scr.im/jbante>.
Expand All @@ -41,62 +43,50 @@ Case (
filterParameters
& Substitute ( filterParameters ; ¶ ; "¶$" )
& ¶ ;

$#Filter.parameterCount = PatternCount ( parameters ; Char ( 13 ) ) ;
$#Filter.parameterLength = Length ( parameters ) ;
$#Filter.step = If ( ~empty ; -1 ; /* Else */ 1 )
];
$#Filter.length = Length ( parameters ) ;
$#Filter.step = If ( ~empty ; 2 ; /* Else */ 1 )
] ;
#Filter ( parameters ; filterParameters )
);
) ;

/* Step 1, check each parameter */
$#Filter.step = 1 ;
Let ( [
$#Filter.i = $#Filter.i + 1 ;
~start = Position ( parameters ; Char ( 13 ) ; 1 ; $#Filter.i - 1 ) + 1 ;
~end = Min (
Position ( parameters ; Char ( 13 ) ; 1 ; $#Filter.i ) ;
$#Filter.parameterLength
);
~pair = Middle ( parameters ; ~start ; ~end - ~start ) ;
~start = $#Filter.end + 1 ;
$#Filter.end = Position ( parameters ; ¶ ; ~start ; 1 ) ;
~endOfList = $#Filter.end = 0 ;
~length =
If ( ~endOfList ;
$#Filter.length + 1 ;
/* Else */ $#Filter.end
)
- ~start ;
~pair = Middle ( parameters ; ~start ; ~length ) ;
~name = Left ( ~pair ; Position ( ~pair ; " = " ; 1 ; 1 ) - 1 ) ;
~include = // only include ~pair if ~name is in filterParameters
Position ( filterParameters ; ¶ & ~name & ¶ ; 1 ; 1 ) > 0 ;
$#Filter.result =
// only include ~pair if ~name is in filterParameters
List (
$#Filter.result ;
If ( Position ( filterParameters ; ¶ & ~name & ¶ ; 1 ; 1 ) > 0;
~pair
)
);
$#Filter.result
& If ( ~include ; ~pair & ¶ ) ;

~endOfList = ~endOfList or $#Filter.end ≥ $#Filter.length ;
$#Filter.step =
If ( $#Filter.i < $#Filter.parameterCount ;
$#Filter.step ;
/* Else */ $#Filter.step + 1
)
];
If ( ~endOfList ; $#Filter.step + 1 ; /* Else */ $#Filter.step )
] ;
#Filter ( parameters ; filterParameters )
);
) ;

/* Step 2, clean-up and return result */
$#Filter.step = 2 or $#Filter.step = -1 ;
$#Filter.step = 2 ;
Let ( [
~error = $#Filter.step = -1 ;
~result = $#Filter.result
// add trailing return if it doesn't exist
& If (
not IsEmpty ( $#Filter.result )
and Right ( $#Filter.result ; 1 ) ≠ ¶ ;
) ;
~result = $#Filter.result ;

// purge variables
$#Filter.i = "" ;
$#Filter.parameterCount = "" ;
$#Filter.parameterLength = "" ;
$#Filter.end = "" ;
$#Filter.length = "" ;
$#Filter.result = "" ;
$#Filter.step = ""
];
If ( ~error ; "" ; /* Else */ ~result )
] ;
~result
)
)
68 changes: 38 additions & 30 deletions Functions/#Name-Value/#GetNameList.fmfn
Expand Up @@ -17,6 +17,8 @@
* DEPENDENCIES: none
*
* HISTORY:
* MODIFIED on 2013-12-24 by Jeremy Bante <http://scr.im/jbante> to improve
* efficiency.
* MODIFIED on 2013-12-23 by John Jones john.christopher@alumni.virginia.edu
* to use Position/Middle.
* CREATED on 2013-01-24 by Daniel Smith dansmith65@gmail.com
Expand All @@ -35,56 +37,62 @@ Case (
[ "¶$" ; ¶ ] ; // remove "$$" prefix
[ "¶¶" ; ¶ ] // remove empty values
) ;

$#GetNameList.parameterCount = PatternCount ( parameters ; Char ( 13 ) ) ;
$#GetNameList.parameterLength = Length ( parameters ) ;
$#GetNameList.step = If ( ~empty ; -1 ; /* Else */ 1 )
];
$#GetNameList.length = Length ( parameters ) ;
$#GetNameList.step = If ( ~empty ; 2 ; /* Else */ 1 )
] ;
#GetNameList ( parameters )
);
) ;

/* Step 1, check each parameter */
$#GetNameList.step = 1 ;
Let ( [
$#GetNameList.i = $#GetNameList.i + 1 ;
~start = Position ( parameters ; Char ( 13 ) ; 1 ; $#GetNameList.i - 1 ) + 1 ;
~end = Min (
Position ( parameters ; Char ( 13 ) ; 1 ; $#GetNameList.i ) ;
$#GetNameList.parameterLength
);
~pair = Middle ( parameters ; ~start ; ~end - ~start ) ;
~start = $#GetNameList.end + 1 ;
$#GetNameList.end = Position ( parameters ; ¶ ; ~start ; 1 ) ;
~endOfList = $#GetNameList.end = 0 ;
~length =
If ( ~endOfList ;
$#GetNameList.length + 1 ;
/* Else */ $#GetNameList.end
)
- ~start ;
~pair = Middle ( parameters ; ~start ; ~length ) ;
~name = Left ( ~pair ; Position ( ~pair ; " = " ; 1 ; 1 ) - 1 ) ;
~include = // only include ~name if it isn't already in the result
Position (
¶ & $#GetNameList.result & ¶ ;
¶ & ~name & ¶ ;
1 ;
1
) = 0 ;
$#GetNameList.result =
// only include ~name if it isn't already in the result
List (
$#GetNameList.result ;
If ( IsEmpty ( FilterValues ( $#GetNameList.result ; ~name ) ) ;
~name
)
);
If ( ~include ; ~name )
) ;

~endOfList =
~endOfList
or $#GetNameList.end ≥ $#GetNameList.length ;
$#GetNameList.step =
If ( $#GetNameList.i < $#GetNameList.parameterCount ;
$#GetNameList.step ;
/* Else */ $#GetNameList.step + 1
If ( ~endOfList ;
$#GetNameList.step + 1 ;
/* Else */ $#GetNameList.step
)
];
] ;
#GetNameList ( parameters )
);
) ;

/* Step 2, clean-up and return result */
$#GetNameList.step = 2 or $#GetNameList.step = -1 ;
$#GetNameList.step = 2 ;
Let ( [
~error = $#GetNameList.step = -1 ;
~result = $#GetNameList.result ;

// purge variables
$#GetNameList.i = "" ;
$#GetNameList.parameterLength = "" ;
$#GetNameList.parameterCount = "" ;
$#GetNameList.end = "" ;
$#GetNameList.length = "" ;
$#GetNameList.result = "" ;
$#GetNameList.step = ""
];
If ( ~error ; "" ; /* Else */ ~result )
] ;
~result
)
)
59 changes: 23 additions & 36 deletions Functions/#Name-Value/#List.fmfn
Expand Up @@ -18,61 +18,48 @@
* DEPENDENCIES: none
*
* HISTORY:
* MODIFIED on 2013-12-24 by Jeremy Bante <http://scr.im/jbante> to
* specially encode newline characters in values, and to update type
* detection to match the # function.
* MODIFIED on 2013-MAY-09 by Daniel Smith dansmith65@gmail.com to encode
* a value like the current version of # ( name ; value ) custom function
* CREATED on 2012-NOV-26 by Daniel Smith dansmith65@gmail.com
* =====================================
*/

Let ( [
// characters used as separators in a date field
~DATECHARS = "\/-" ;
// characters used as separators in a time field
~TIMECHARS = ":" ;

~text = GetAsText ( value ) ;
~number = GetAsNumber ( value ) ;
~validDate =
IsValid ( GetAsDate ( ~text ) )
and not IsEmpty ( ~number ) ;
~validTime =
IsValid ( GetAsTime ( ~text ) )
and Position ( ~text ; ":" ; 1 ; 1 ) > 0
and not IsEmpty ( ~number ) ;
~value =
Case (
// test for specific values that will be treated as a number in the next section
value = "" or value = "?" ;
Quote ( value ) ;

value ≠ GetAsNumber ( value ) ;
Quote ( value ) ;

// at this point, value is a number, timestamp, date, or time
// negative time value
value < 0 and not IsEmpty ( Filter ( value ; ~TIMECHARS ) ) ;
"GetAsTime ( " & Quote ( value ) & " )" ;

not IsEmpty ( Filter ( value ; ~DATECHARS ) )
and not IsEmpty ( Filter ( value ; ~TIMECHARS ) ) ;
~validTime and ~validDate ;
"GetAsTimestamp ( " & Quote ( value ) & " )" ;

not IsEmpty ( Filter ( value ; ~TIMECHARS ) ) ;
~validTime ;
"GetAsTime ( " & Quote ( value ) & " )" ;

/**
* At this point, if value is less than 1, it must be either
* a negative number or a decimal exponent.
* This section must be after test for time because time can
* contain a negative number.
* This section should be before test for date, because a date
* can contain a -, which is also used for a negative number.
*/
value < 1 ;
GetAsNumber ( value ) ;

not IsEmpty ( Filter ( value ; ~DATECHARS ) ) ;
~validDate ;
"GetAsDate ( " & Quote ( value ) & " )" ;

/**
* either a number, or:
* if the ~DATECHARS and ~TIMECHARS variables do not contain the
* separator chars in use on the current computer, store the
* date/time/timestamp as a number
*/
~text ≠ GetAsText ( ~number ) ;
Substitute ( Quote ( value ) ;
[ Char ( 10 ) ; "\" & Char ( 10 ) & \"" ] ;
[ Char ( 8232 ) ; "\" & Char ( 8232 ) & \"" ] ;
[ Char ( 8233 ) ; "\" & Char ( 8233 ) & \"" ]
) ;

/* Else */
GetAsNumber ( value )
~number
)
] ;
Case (
Expand Down

0 comments on commit c3ccf0b

Please sign in to comment.