Skip to content

Commit

Permalink
Support for null safety, update to lint, some small related refactoring.
Browse files Browse the repository at this point in the history
  • Loading branch information
cardilloscreations committed Jun 19, 2021
1 parent 9be24e5 commit 188d39f
Show file tree
Hide file tree
Showing 19 changed files with 179 additions and 163 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 1.0.0

* _Tested with dart `2.13`._
* Refactored to support for null safety.
* Updated SDK constraints to `>=2.12.0 <3.0.0` for null safety.
* Switch to using `package:lints`.

## 0.2.1

* _Minor pub updates and tested with dart `2.10`._
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
[![Build Status](https://travis-ci.com/raycardillo/dart_phonetics.svg?branch=master)](https://travis-ci.com/raycardillo/dart_phonetics)
[![Pub package](https://img.shields.io/pub/v/dart_phonetics)](https://pub.dev/packages/dart_phonetics)
[![Dartdoc reference](https://img.shields.io/badge/dartdoc-reference-blue)](https://pub.dev/documentation/dart_phonetics/latest/)
[![style: lint](https://img.shields.io/badge/style-lint-4BC0F5.svg)](https://pub.dev/packages/lint)
[![Project license](https://img.shields.io/badge/license-Apache%202.0-informational)](https://www.apache.org/licenses/LICENSE-2.0)

A collection of phonetic algorithms for [Dart](https://dart.dev/) and [Flutter](https://flutter.dev/). These algorithms help find words or names that sound similar by generating an encoding that can be compared or indexed for fuzzy searching.
Expand Down
7 changes: 6 additions & 1 deletion analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
include: package:pedantic/analysis_options.yaml
include: package:lints/recommended.yaml

linter:
rules:
constant_identifier_names: false
non_constant_identifier_names: false
7 changes: 3 additions & 4 deletions example/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import 'package:dart_phonetics/dart_phonetics.dart';
void _printResult(PhoneticEncoder encoder, String input) {
final encoding = encoder.encode(input);
print(
'${encoder?.runtimeType?.toString()} - "$input"\n primary = ${encoding?.primary}\n alternate = ${encoding?.alternates}\n');
'${encoder.runtimeType.toString()} - "$input"\n primary = ${encoding?.primary}\n alternate = ${encoding?.alternates}\n');
}

void main() {
Expand All @@ -13,7 +13,7 @@ void main() {
_printResult(soundex, inputString);

final customSoundex = Soundex.fromMapping(Soundex.americanMapping,
maxLength: null, paddingEnabled: false, ignoreHW: false);
maxLength: 0, paddingEnabled: false, ignoreHW: false);
_printResult(customSoundex, inputString);

final refinedSoundex = RefinedSoundex.defaultEncoder;
Expand All @@ -22,8 +22,7 @@ void main() {
final nysiisOriginal = Nysiis.originalEncoder;
_printResult(nysiisOriginal, inputString);

final nysiisModified =
Nysiis.withOptions(maxLength: null, enableModified: true);
final nysiisModified = Nysiis.withOptions(maxLength: 0, enableModified: true);
_printResult(nysiisModified, inputString);

final doubleMetaphone = DoubleMetaphone.withMaxLength(12);
Expand Down
28 changes: 16 additions & 12 deletions lib/src/double_metaphone.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,22 @@ class _DoubleMetaphoneEncoding {
/// Buffer used for writing alternate encoding.
final StringBuffer _alternate = StringBuffer();

/// Max length to encode (or `null` if no max length).
/// Max length to encode (defaults to `0` for no max length).
final int _maxLength;

/// Internal constructor.
_DoubleMetaphoneEncoding([this._maxLength]);
_DoubleMetaphoneEncoding([this._maxLength = 0]);

/// Append a [charCode] to the primary encoding.
void appendPrimary(final int charCode) {
if (_maxLength == null || _primary.length < _maxLength) {
if (_maxLength <= 0 || _primary.length < _maxLength) {
_primary.writeCharCode(charCode);
}
}

/// Append a [charCode] to the alternate encoding.
void appendAlternate(final int charCode) {
if (_maxLength == null || _alternate.length < _maxLength) {
if (_maxLength <= 0 || _alternate.length < _maxLength) {
_alternate.writeCharCode(charCode);
}
}
Expand Down Expand Up @@ -97,11 +97,10 @@ class _DoubleMetaphoneEncoding {
}

/// Returns `true` if the encoding is maxed out (both encodings are at the
/// max length), `false` otherwise (or if [_maxLength] is `null`).
/// max length), `false` otherwise (or if [_maxLength] is `0`).
bool isMaxedOut() {
return _maxLength != null &&
_primary.length >= _maxLength &&
_alternate.length >= _maxLength;
return _maxLength > 0 && _primary.length >= _maxLength && _alternate
.length >= _maxLength;
}

/// Returns the string value of the primary encoding. This renders the
Expand Down Expand Up @@ -142,7 +141,7 @@ class DoubleMetaphone implements PhoneticEncoder {
/// Default metaphone encoding length to use.
static const int defaultMaxLength = 4;

/// Maximum length of the encoding, where `null` indicates no maximum.
/// Maximum length of the encoding, where `0` indicates no maximum.
final int maxLength;

// Set.contains() for single character matches are fast and convenient
Expand Down Expand Up @@ -246,13 +245,18 @@ class DoubleMetaphone implements PhoneticEncoder {

//#endregion

/// Encodes a string using the Double Metaphone algorithm as configured.
///
/// Per specification, the encoding always contains two values. If there is
/// no alternate, the primary and the alternate encodings will be the same.
///
/// Returns a [PhoneticEncoding] for the [input] String or
/// `null` if the [input] is empty (after cleaning up).
@override
PhoneticEncoding encode(String input) {
PhoneticEncoding? encode(String input) {
// clean up the input and convert to uppercase
input = PhoneticUtils.clean(input);
if (input == null) {
if (input.isEmpty) {
return null;
}

Expand Down Expand Up @@ -368,7 +372,7 @@ class DoubleMetaphone implements PhoneticEncoder {

final primary = encoding.primary;
final alternate = encoding.alternate;
return PhoneticEncoding(primary, (alternate.isEmpty ? null : {alternate}));
return PhoneticEncoding(primary, {alternate});
}

//#region Special Encoding Rules
Expand Down
10 changes: 5 additions & 5 deletions lib/src/encoder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@
/// phonetically encoding an input string.
class PhoneticEncoderException implements Exception {
/// The input that was being processed when the exception occurred.
/// This should only be `null` if the input being encoded was `null`.
/// This may be empty if the input being encoded was empty after cleanup.
final String input;

/// A message describing the problem that was encountered.
final String message;

/// Optionally indicates another exception that was the root cause.
final Exception cause;
final Exception? cause;

/// Creates a new PhoneticEncoderException with an optional root [cause].
PhoneticEncoderException(this.input, this.message, [this.cause]);
Expand All @@ -49,7 +49,7 @@ class PhoneticEncoding {
final String primary;

/// An alternative phonetic encoding for algorithms that support this.
final Set<String> alternates;
final Set<String>? alternates;

/// Creates an instance of this data class.
PhoneticEncoding(this.primary, [this.alternates]);
Expand All @@ -63,6 +63,6 @@ class PhoneticEncoding {

/// The common interface for all phonetic encoders.
abstract class PhoneticEncoder {
/// Returns a [PhoneticEncoding] for the [input] String.
PhoneticEncoding encode(String input);
/// Returns a [PhoneticEncoding] for the [input] String or `null`.
PhoneticEncoding? encode(String input);
}
15 changes: 8 additions & 7 deletions lib/src/nysiis.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class Nysiis implements PhoneticEncoder {
/// Default encoding length to use for the modified algorithm.
static const int defaultModifiedMaxLength = 8;

/// Maximum length of the encoding, where `null` indicates no maximum.
/// Maximum length of the encoding, where `0` indicates no maximum.
final int maxLength;

/// Indicates if the "modified" rules should be applied when encoding.
Expand Down Expand Up @@ -276,9 +276,7 @@ class Nysiis implements PhoneticEncoder {
// NOTE: per specification, this loop starts at the second character.
for (var i = 1; i < chars.length; i++) {
final char = chars[i];
if (char == null) {
break;
} else if (PhoneticUtils.isSpecialCharacter(char)) {
if (PhoneticUtils.isSpecialCharacter(char)) {
continue;
}

Expand Down Expand Up @@ -401,11 +399,14 @@ class Nysiis implements PhoneticEncoder {

/// Encodes a string using the NYSIIS algorithm as configured. This encoder
/// does not produce any [PhoneticEncoding.alternates] values.
///
/// Returns a [PhoneticEncoding] for the [input] String or
/// `null` if the [input] is empty (after cleaning up).
@override
PhoneticEncoding encode(String input) {
PhoneticEncoding? encode(String input) {
// clean up the input and convert to uppercase
input = PhoneticUtils.clean(input);
if (input == null) {
if (input.isEmpty) {
return null;
}

Expand All @@ -430,7 +431,7 @@ class Nysiis implements PhoneticEncoder {

// truncate the encoding to maxLength if required
var finalEncoding = String.fromCharCodes(encoding);
if (maxLength != null && finalEncoding.length > maxLength) {
if (maxLength > 0 && finalEncoding.length > maxLength) {
finalEncoding = finalEncoding.substring(0, maxLength);
}

Expand Down
18 changes: 10 additions & 8 deletions lib/src/refined_soundex.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class RefinedSoundex implements PhoneticEncoder {
/// ignore the input character and do not encode it (e.g., vowels).
final Map<int, int> soundexMapping;

/// Maximum length of the encoding (and how much to pad if [paddingEnabled]).
/// Maximum length of the encoding, where `0` indicates no maximum.
final int maxLength;

/// This is a default mapping of the 26 letters used in US English.
Expand Down Expand Up @@ -81,21 +81,23 @@ class RefinedSoundex implements PhoneticEncoder {
/// Creates a custom Soundex instance. This constructor can be used to
/// provide custom mappings for non-Western character sets, etc.
factory RefinedSoundex.fromMapping(final Map<int, int> soundexMapping,
{int maxLength}) =>
{int maxLength = 0}) =>
RefinedSoundex._internal(Map.unmodifiable(soundexMapping), maxLength);

/// Gets the [defaultEncoder] instance of a RefinedSoundex encoder.
factory RefinedSoundex() => defaultEncoder;

//#endregion

/// Returns a [PhoneticEncoding] for the [input] String.
/// Returns `null` if the input is `null` or empty (after cleaning up).
/// Encodes a string using the Refined Soundex algorithm as configured.
///
/// Returns a [PhoneticEncoding] for the [input] String or
/// `null` if the [input] is empty (after cleaning up).
@override
PhoneticEncoding encode(String input) {
PhoneticEncoding? encode(String input) {
// clean up the input and convert to uppercase
input = PhoneticUtils.clean(input, allowLatin: false);
if (input == null) {
if (input.isEmpty) {
return null;
}

Expand All @@ -105,7 +107,7 @@ class RefinedSoundex implements PhoneticEncoder {
// always write first character
soundex.writeCharCode(input.codeUnitAt(0));

int last, current;
int? last, current;
last = $asterisk;

// encode all characters
Expand All @@ -117,7 +119,7 @@ class RefinedSoundex implements PhoneticEncoder {
soundex.writeCharCode(current);
}

if (maxLength != null && soundex.length >= maxLength) {
if (maxLength > 0 && soundex.length >= maxLength) {
break;
}

Expand Down
37 changes: 20 additions & 17 deletions lib/src/soundex.dart
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ class Soundex implements PhoneticEncoder {
/// The character to use for padding (when [paddingEnabled] is `true`).
final int paddingChar;

/// Maximum length of the encoding (and how much to pad if [paddingEnabled]).
/// Maximum length of the encoding, where `0` indicates no maximum,
/// and how much to pad if [paddingEnabled].
final int maxLength;

/// This is a default mapping of the 26 letters used in US English.
Expand Down Expand Up @@ -186,13 +187,13 @@ class Soundex implements PhoneticEncoder {
return input.split(RegExp(r'\s*-\s*'));
}

/// Returns a single encoding for the [input] String.
/// Returns `null` if the input is `null` or empty (after cleaning up).
/// Returns a [PhoneticEncoding] for the [input] String or
/// an empty string if the [input] is empty (after cleaning up).
String _encode(String input) {
// clean up the input and convert to uppercase
input = PhoneticUtils.clean(input, allowLatin: false);
if (input == null) {
return null;
if (input.isEmpty) {
return input;
}

// we'll write to a buffer to avoid string copies
Expand Down Expand Up @@ -228,13 +229,13 @@ class Soundex implements PhoneticEncoder {
}
}

if (maxLength != null && soundex.length >= maxLength) {
if (maxLength > 0 && soundex.length >= maxLength) {
break;
}
}

// pad the encoding if required
if (paddingEnabled && maxLength != null) {
if (paddingEnabled && maxLength > 0) {
while (soundex.length < maxLength) {
soundex.writeCharCode(paddingChar);
}
Expand All @@ -252,11 +253,15 @@ class Soundex implements PhoneticEncoder {
}
}

/// Returns a [PhoneticEncoding] for the [input] String.
/// Returns `null` if the input is `null` or empty (after cleaning up).
/// Encodes a string using the Soundex algorithm as configured.
///
/// Returns a [PhoneticEncoding] for the [input] String or
/// `null` if the [input] is empty (after cleaning up).
@override
PhoneticEncoding encode(String input) {
if (input == null || input.isEmpty) {
PhoneticEncoding? encode(String input) {
// clean up the input and convert to uppercase
input = PhoneticUtils.clean(input, allowLatin: false);
if (input.isEmpty) {
return null;
}

Expand Down Expand Up @@ -285,17 +290,15 @@ class Soundex implements PhoneticEncoder {
// now go through all parts and add more alternates
while (iterator.moveNext()) {
final part = iterator.current;
if (part != null) {
alternates.add(_encode(part));
if (prefixesEnabled) {
_addTrimmedPrefixToAlternates(alternates, part);
}
alternates.add(_encode(part));
if (prefixesEnabled) {
_addTrimmedPrefixToAlternates(alternates, part);
}
}

// remove the primary if it made it into the alternate list from others
alternates.remove(primary);

return PhoneticEncoding(primary, alternates.isEmpty ? null : alternates);
return PhoneticEncoding(primary, alternates);
}
}
8 changes: 4 additions & 4 deletions lib/src/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ class PhoneticUtils {
/// need to do additional cleaning if you're working with strings
/// that are particularly dirty.
static String clean(final String value, {bool allowLatin = true}) {
if (value == null || value.isEmpty) {
return null;
if (value.isEmpty) {
return value;
}

final cleaned = value
Expand All @@ -136,7 +136,7 @@ class PhoneticUtils {
.replaceAll(
(allowLatin) ? _cleanLatinAllowed : _cleanLatinNotAllowed, '');

return cleaned.isEmpty ? null : cleaned;
return cleaned;
}

/// Returns the character from [value] at [index] or [$nul] if the index is
Expand Down Expand Up @@ -186,7 +186,7 @@ class PhoneticUtils {
///
/// Despite the name, this is actually a measure of similarity.
/// This naming is consistent with the SQL `DIFFERENCE` function definition.
static int differenceEncoded(final String e1, final String e2) {
static int differenceEncoded(final String? e1, final String? e2) {
if (e1 == null || e1.isEmpty || e2 == null || e2.isEmpty) {
return 0;
}
Expand Down
3 changes: 1 addition & 2 deletions misc/experiments/single_char_exp.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@ void main() {
final watch = Stopwatch();

const numIterations = 2000000;
var vowelsFound;
var vowelsFound = 0;

vowelsFound = 0;
print('running if statement matching...');
watch.start();
for (var i = 0; i < numIterations; i++) {
Expand Down
Loading

0 comments on commit 188d39f

Please sign in to comment.