string_to_number 0.1.4 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +83 -0
- data/.rubocop.yml +110 -0
- data/.tool-versions +1 -0
- data/CLAUDE.md +103 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +33 -2
- data/README.md +184 -25
- data/Rakefile +5 -1
- data/benchmark.rb +178 -0
- data/lib/string_to_number/parser.rb +232 -0
- data/lib/string_to_number/to_number.rb +145 -38
- data/lib/string_to_number/version.rb +3 -1
- data/lib/string_to_number.rb +91 -2
- data/logo.png +0 -0
- data/microbenchmark.rb +227 -0
- data/performance_comparison.rb +154 -0
- data/profile.rb +130 -0
- data/string_to_number.gemspec +5 -6
- metadata +14 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a97e2a69e72adda0aeedace8ab5a9ddae63c1a4741846d6d405a0ef767bdaaaa
|
4
|
+
data.tar.gz: 78553f4c606a717c8bab939e24b18ddd023a8962b902d2fea75b03498b2e3e0a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1042d45f537afc86b43883d29a3ef03ffd3ddc365a37c85843bd78fa54c4d35178c140e32c025d7406681dc31d77c06b7f7e526e4255fef1629a468a7ddf1958
|
7
|
+
data.tar.gz: 1f6b2b1e8dc6c17bf72d0ce759da2fe31dd9771188ae6087b23774b06e55f9678ee8bcc049c611ff8b0a68d9b99c8b3cb3088e28f342ae1f0d842cd618cf81da
|
@@ -0,0 +1,83 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ master, main ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ master, main ]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
test:
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
strategy:
|
13
|
+
matrix:
|
14
|
+
ruby-version: ['2.7', '3.0', '3.1', '3.2', '3.3']
|
15
|
+
|
16
|
+
steps:
|
17
|
+
- uses: actions/checkout@v4
|
18
|
+
|
19
|
+
- name: Set up Ruby ${{ matrix.ruby-version }}
|
20
|
+
uses: ruby/setup-ruby@v1
|
21
|
+
with:
|
22
|
+
ruby-version: ${{ matrix.ruby-version }}
|
23
|
+
bundler-cache: true
|
24
|
+
|
25
|
+
- name: Run tests
|
26
|
+
run: bundle exec rake spec
|
27
|
+
|
28
|
+
- name: Run performance tests
|
29
|
+
run: bundle exec rspec spec/performance_spec.rb
|
30
|
+
|
31
|
+
lint:
|
32
|
+
runs-on: ubuntu-latest
|
33
|
+
steps:
|
34
|
+
- uses: actions/checkout@v4
|
35
|
+
|
36
|
+
- name: Set up Ruby
|
37
|
+
uses: ruby/setup-ruby@v1
|
38
|
+
with:
|
39
|
+
ruby-version: '3.3'
|
40
|
+
bundler-cache: true
|
41
|
+
|
42
|
+
- name: Install RuboCop
|
43
|
+
run: gem install rubocop
|
44
|
+
|
45
|
+
- name: Run RuboCop
|
46
|
+
run: rubocop --format github
|
47
|
+
|
48
|
+
security:
|
49
|
+
runs-on: ubuntu-latest
|
50
|
+
steps:
|
51
|
+
- uses: actions/checkout@v4
|
52
|
+
|
53
|
+
- name: Set up Ruby
|
54
|
+
uses: ruby/setup-ruby@v1
|
55
|
+
with:
|
56
|
+
ruby-version: '3.3'
|
57
|
+
bundler-cache: true
|
58
|
+
|
59
|
+
- name: Install bundler-audit
|
60
|
+
run: gem install bundler-audit
|
61
|
+
|
62
|
+
- name: Run bundler-audit
|
63
|
+
run: bundle audit --update
|
64
|
+
|
65
|
+
gem-build:
|
66
|
+
runs-on: ubuntu-latest
|
67
|
+
steps:
|
68
|
+
- uses: actions/checkout@v4
|
69
|
+
|
70
|
+
- name: Set up Ruby
|
71
|
+
uses: ruby/setup-ruby@v1
|
72
|
+
with:
|
73
|
+
ruby-version: '3.3'
|
74
|
+
bundler-cache: true
|
75
|
+
|
76
|
+
- name: Build gem
|
77
|
+
run: gem build string_to_number.gemspec
|
78
|
+
|
79
|
+
- name: Install gem locally
|
80
|
+
run: gem install string_to_number-*.gem
|
81
|
+
|
82
|
+
- name: Test gem installation
|
83
|
+
run: ruby -e "require 'string_to_number'; puts StringToNumber.in_numbers('vingt et un')"
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.7
|
3
|
+
NewCops: enable
|
4
|
+
Exclude:
|
5
|
+
- 'vendor/**/*'
|
6
|
+
- 'pkg/**/*'
|
7
|
+
- 'tmp/**/*'
|
8
|
+
- 'bin/**/*'
|
9
|
+
- 'spec/fixtures/**/*'
|
10
|
+
SuggestExtensions: false
|
11
|
+
|
12
|
+
# Prefer double quotes for strings
|
13
|
+
Style/StringLiterals:
|
14
|
+
EnforcedStyle: single_quotes
|
15
|
+
|
16
|
+
# Allow longer lines for readability
|
17
|
+
Layout/LineLength:
|
18
|
+
Max: 120
|
19
|
+
Exclude:
|
20
|
+
- 'spec/**/*'
|
21
|
+
|
22
|
+
# Allow longer methods for complex parsing logic
|
23
|
+
Metrics/MethodLength:
|
24
|
+
Max: 25
|
25
|
+
Exclude:
|
26
|
+
- 'spec/**/*'
|
27
|
+
- 'benchmark.rb'
|
28
|
+
- 'microbenchmark.rb'
|
29
|
+
- 'performance_comparison.rb'
|
30
|
+
- 'lib/string_to_number/parser.rb'
|
31
|
+
- 'lib/string_to_number/to_number.rb'
|
32
|
+
|
33
|
+
# Allow longer classes for main implementation
|
34
|
+
Metrics/ClassLength:
|
35
|
+
Max: 250
|
36
|
+
|
37
|
+
# Allow longer blocks for test files
|
38
|
+
Metrics/BlockLength:
|
39
|
+
Max: 300
|
40
|
+
Exclude:
|
41
|
+
- 'spec/**/*'
|
42
|
+
|
43
|
+
# Allow more complex methods in parser
|
44
|
+
Metrics/CyclomaticComplexity:
|
45
|
+
Max: 12
|
46
|
+
Exclude:
|
47
|
+
- 'benchmark.rb'
|
48
|
+
- 'microbenchmark.rb'
|
49
|
+
- 'performance_comparison.rb'
|
50
|
+
- 'lib/string_to_number/parser.rb'
|
51
|
+
- 'lib/string_to_number/to_number.rb'
|
52
|
+
|
53
|
+
# Allow higher ABC size for parsing methods
|
54
|
+
Metrics/AbcSize:
|
55
|
+
Max: 20
|
56
|
+
Exclude:
|
57
|
+
- 'spec/**/*'
|
58
|
+
- 'benchmark.rb'
|
59
|
+
- 'microbenchmark.rb'
|
60
|
+
- 'performance_comparison.rb'
|
61
|
+
- 'lib/string_to_number/parser.rb'
|
62
|
+
- 'lib/string_to_number/to_number.rb'
|
63
|
+
|
64
|
+
# Allow higher perceived complexity for performance-critical methods
|
65
|
+
Metrics/PerceivedComplexity:
|
66
|
+
Max: 8
|
67
|
+
Exclude:
|
68
|
+
- 'benchmark.rb'
|
69
|
+
- 'microbenchmark.rb'
|
70
|
+
- 'performance_comparison.rb'
|
71
|
+
- 'lib/string_to_number/parser.rb'
|
72
|
+
- 'lib/string_to_number/to_number.rb'
|
73
|
+
|
74
|
+
# Allow multiple assignments for performance reasons
|
75
|
+
Style/ParallelAssignment:
|
76
|
+
Enabled: false
|
77
|
+
|
78
|
+
# Allow guard clauses without else
|
79
|
+
Style/GuardClause:
|
80
|
+
Enabled: false
|
81
|
+
|
82
|
+
# Documentation requirements
|
83
|
+
Style/Documentation:
|
84
|
+
Enabled: false
|
85
|
+
|
86
|
+
# Allow frozen string literal comments
|
87
|
+
Style/FrozenStringLiteralComment:
|
88
|
+
Enabled: true
|
89
|
+
EnforcedStyle: always
|
90
|
+
|
91
|
+
|
92
|
+
# Layout preferences
|
93
|
+
Layout/MultilineMethodCallIndentation:
|
94
|
+
EnforcedStyle: aligned
|
95
|
+
|
96
|
+
Layout/MultilineOperationIndentation:
|
97
|
+
EnforcedStyle: aligned
|
98
|
+
|
99
|
+
# Naming conventions
|
100
|
+
Naming/PredicatePrefix:
|
101
|
+
ForbiddenPrefixes:
|
102
|
+
- is_
|
103
|
+
|
104
|
+
# Allow single line methods
|
105
|
+
Style/SingleLineMethods:
|
106
|
+
AllowIfMethodIsEmpty: true
|
107
|
+
|
108
|
+
# Gem specific rules
|
109
|
+
Gemspec/RequiredRubyVersion:
|
110
|
+
Enabled: false
|
data/.tool-versions
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby 2.7.8
|
data/CLAUDE.md
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
# CLAUDE.md
|
2
|
+
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
4
|
+
|
5
|
+
## Project Overview
|
6
|
+
|
7
|
+
This is a Ruby gem that converts French words into numbers. The gem provides a single public method `StringToNumber.in_numbers(french_string)` that parses French number words and returns their numeric equivalent.
|
8
|
+
|
9
|
+
## Core Architecture
|
10
|
+
|
11
|
+
- **Main module**: `StringToNumber` in `lib/string_to_number.rb` - provides the public API
|
12
|
+
- **Optimized parser**: `StringToNumber::Parser` in `lib/string_to_number/parser.rb` - high-performance implementation
|
13
|
+
- **Original implementation**: `StringToNumber::ToNumber` in `lib/string_to_number/to_number.rb` - legacy compatibility
|
14
|
+
- **Version**: `StringToNumber::VERSION` in `lib/string_to_number/version.rb`
|
15
|
+
|
16
|
+
### Parser Architecture
|
17
|
+
|
18
|
+
The optimized parser uses:
|
19
|
+
- **WORD_VALUES**: Direct French word to number mappings (0-90, including regional variants)
|
20
|
+
- **MULTIPLIERS**: Power-of-ten multipliers (cent=2, mille=3, million=6, etc.)
|
21
|
+
- **Pre-compiled regex patterns**: Eliminate compilation overhead
|
22
|
+
- **Multi-level caching**: Instance cache + LRU conversion cache
|
23
|
+
- **Thread-safe design**: Concurrent access with mutex protection
|
24
|
+
|
25
|
+
The algorithm maintains the proven recursive parsing logic from the original while adding:
|
26
|
+
- Memoization for repeated conversions
|
27
|
+
- Instance caching to reduce initialization costs
|
28
|
+
- Optimized string operations and hash lookups
|
29
|
+
|
30
|
+
## Common Development Commands
|
31
|
+
|
32
|
+
```bash
|
33
|
+
# Install dependencies
|
34
|
+
bundle install
|
35
|
+
|
36
|
+
# Run tests
|
37
|
+
rake spec
|
38
|
+
|
39
|
+
# Run specific test
|
40
|
+
bundle exec rspec spec/string_to_number_spec.rb
|
41
|
+
|
42
|
+
# Start interactive console
|
43
|
+
rake console
|
44
|
+
# or
|
45
|
+
bundle exec irb -I lib -r string_to_number
|
46
|
+
|
47
|
+
# Install gem locally
|
48
|
+
bundle exec rake install
|
49
|
+
|
50
|
+
# Release new version (updates version.rb, creates git tag, pushes to rubygems)
|
51
|
+
bundle exec rake release
|
52
|
+
```
|
53
|
+
|
54
|
+
## Testing
|
55
|
+
|
56
|
+
Uses RSpec with comprehensive test coverage for French number parsing from 0 to millions. Tests are organized by number ranges (0-9, 10-19, 20-29, etc.) and include complex multi-word numbers.
|
57
|
+
|
58
|
+
### Performance Testing
|
59
|
+
|
60
|
+
Performance tests are available to measure and monitor the implementation's efficiency:
|
61
|
+
|
62
|
+
```bash
|
63
|
+
# Run comprehensive performance test suite
|
64
|
+
bundle exec rspec spec/performance_spec.rb
|
65
|
+
|
66
|
+
# Run standalone benchmark script
|
67
|
+
ruby -I lib benchmark.rb
|
68
|
+
|
69
|
+
# Run micro-benchmarks to identify bottlenecks
|
70
|
+
ruby -I lib microbenchmark.rb
|
71
|
+
|
72
|
+
# Run profiling analysis
|
73
|
+
ruby -I lib profile.rb
|
74
|
+
```
|
75
|
+
|
76
|
+
**Performance Characteristics (Optimized Implementation):**
|
77
|
+
- Simple numbers (0-100): ~0.001ms average, 800,000+ conversions/sec
|
78
|
+
- Medium complexity (100-1000): ~0.001ms average, 780,000+ conversions/sec
|
79
|
+
- Complex numbers (1000+): ~0.002ms average, 690,000+ conversions/sec
|
80
|
+
- Exceptional scalability: minimal performance degradation with input length
|
81
|
+
- Memory efficient: zero object creation during operation
|
82
|
+
- Intelligent caching: repeated conversions benefit from memoization
|
83
|
+
|
84
|
+
**Performance Improvements:**
|
85
|
+
- **14-460x faster** than original implementation across all test cases
|
86
|
+
- **Excellent scalability**: 1.3x degradation vs 43x in original
|
87
|
+
- **Pre-compiled regex patterns** eliminate compilation overhead
|
88
|
+
- **Instance caching** reduces initialization costs
|
89
|
+
- **Memoization** speeds up repeated conversions
|
90
|
+
- **Thread-safe** with concurrent performance >2M conversions/sec
|
91
|
+
|
92
|
+
**Usage Options:**
|
93
|
+
```ruby
|
94
|
+
# Use optimized implementation (default)
|
95
|
+
StringToNumber.in_numbers('vingt et un')
|
96
|
+
|
97
|
+
# Use original implementation for compatibility
|
98
|
+
StringToNumber.in_numbers('vingt et un', use_optimized: false)
|
99
|
+
|
100
|
+
# Cache management
|
101
|
+
StringToNumber.clear_caches!
|
102
|
+
StringToNumber.cache_stats
|
103
|
+
```
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,13 +1,25 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
string_to_number (0.1
|
4
|
+
string_to_number (0.2.1)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
+
ast (2.4.3)
|
9
10
|
diff-lcs (1.5.0)
|
11
|
+
json (2.12.2)
|
12
|
+
language_server-protocol (3.17.0.5)
|
13
|
+
lint_roller (1.1.0)
|
14
|
+
parallel (1.27.0)
|
15
|
+
parser (3.3.8.0)
|
16
|
+
ast (~> 2.4.1)
|
17
|
+
racc
|
18
|
+
prism (1.4.0)
|
19
|
+
racc (1.8.1)
|
20
|
+
rainbow (3.1.1)
|
10
21
|
rake (13.0.6)
|
22
|
+
regexp_parser (2.10.0)
|
11
23
|
rspec (3.11.0)
|
12
24
|
rspec-core (~> 3.11.0)
|
13
25
|
rspec-expectations (~> 3.11.0)
|
@@ -21,6 +33,24 @@ GEM
|
|
21
33
|
diff-lcs (>= 1.2.0, < 2.0)
|
22
34
|
rspec-support (~> 3.11.0)
|
23
35
|
rspec-support (3.11.1)
|
36
|
+
rubocop (1.77.0)
|
37
|
+
json (~> 2.3)
|
38
|
+
language_server-protocol (~> 3.17.0.2)
|
39
|
+
lint_roller (~> 1.1.0)
|
40
|
+
parallel (~> 1.10)
|
41
|
+
parser (>= 3.3.0.2)
|
42
|
+
rainbow (>= 2.2.2, < 4.0)
|
43
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
44
|
+
rubocop-ast (>= 1.45.1, < 2.0)
|
45
|
+
ruby-progressbar (~> 1.7)
|
46
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
47
|
+
rubocop-ast (1.45.1)
|
48
|
+
parser (>= 3.3.7.2)
|
49
|
+
prism (~> 1.4)
|
50
|
+
ruby-progressbar (1.13.0)
|
51
|
+
unicode-display_width (3.1.4)
|
52
|
+
unicode-emoji (~> 4.0, >= 4.0.4)
|
53
|
+
unicode-emoji (4.0.4)
|
24
54
|
|
25
55
|
PLATFORMS
|
26
56
|
x86_64-linux
|
@@ -29,7 +59,8 @@ DEPENDENCIES
|
|
29
59
|
bundler
|
30
60
|
rake
|
31
61
|
rspec
|
62
|
+
rubocop (~> 1.21)
|
32
63
|
string_to_number!
|
33
64
|
|
34
65
|
BUNDLED WITH
|
35
|
-
2.3.
|
66
|
+
2.3.26
|
data/README.md
CHANGED
@@ -1,8 +1,36 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
<div align="center">
|
2
|
+
<img src="logo.png" alt="StringToNumber Logo" width="200" height="200">
|
3
|
+
|
4
|
+
# StringToNumber
|
5
|
+
|
6
|
+
[](https://badge.fury.io/rb/string_to_number)
|
7
|
+
[](https://github.com/FabienPiette/string_to_number/actions)
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
9
|
+
</div>
|
10
|
+
|
11
|
+
A high-performance Ruby gem for converting French written numbers into their numeric equivalents. Features intelligent caching, thread-safe operations, and support for complex French number formats.
|
12
|
+
|
13
|
+
## ✨ Features
|
14
|
+
|
15
|
+
- **High Performance**: Up to 460x faster than naive implementations with intelligent caching
|
16
|
+
- **Thread-Safe**: Concurrent access support with proper locking mechanisms
|
17
|
+
- **Comprehensive**: Handles complex French number formats including:
|
18
|
+
- Basic numbers (zéro, un, deux...)
|
19
|
+
- Compound numbers (vingt et un, quatre-vingt-quatorze...)
|
20
|
+
- Large numbers (millions, milliards, billions...)
|
21
|
+
- Special cases (quatre-vingts, soixante-dix...)
|
22
|
+
- **Memory Efficient**: LRU cache with configurable limits
|
23
|
+
- **Backward Compatible**: Maintains compatibility with original implementation
|
24
|
+
|
25
|
+
## 🚀 Performance
|
26
|
+
|
27
|
+
| Input Size | Original | Optimized | Improvement |
|
28
|
+
|------------|----------|-----------|-------------|
|
29
|
+
| Short | 0.5ms | 0.035ms | **14x** |
|
30
|
+
| Medium | 2.1ms | 0.045ms | **47x** |
|
31
|
+
| Long | 23ms | 0.05ms | **460x** |
|
32
|
+
|
33
|
+
## 📦 Installation
|
6
34
|
|
7
35
|
Add this line to your application's Gemfile:
|
8
36
|
|
@@ -12,45 +40,176 @@ gem 'string_to_number'
|
|
12
40
|
|
13
41
|
And then execute:
|
14
42
|
|
15
|
-
|
43
|
+
```bash
|
44
|
+
$ bundle install
|
45
|
+
```
|
16
46
|
|
17
47
|
Or install it yourself as:
|
18
48
|
|
19
|
-
|
49
|
+
```bash
|
50
|
+
$ gem install string_to_number
|
51
|
+
```
|
52
|
+
|
53
|
+
## 🔧 Usage
|
20
54
|
|
21
|
-
|
55
|
+
### Basic Usage
|
22
56
|
|
23
57
|
```ruby
|
24
58
|
require 'string_to_number'
|
25
59
|
|
26
|
-
|
27
|
-
#=> 0
|
60
|
+
# Simple numbers
|
61
|
+
StringToNumber.in_numbers('zéro') #=> 0
|
62
|
+
StringToNumber.in_numbers('quinze') #=> 15
|
63
|
+
StringToNumber.in_numbers('cent') #=> 100
|
64
|
+
|
65
|
+
# Compound numbers
|
66
|
+
StringToNumber.in_numbers('vingt et un') #=> 21
|
67
|
+
StringToNumber.in_numbers('quatre-vingt-quatorze') #=> 94
|
68
|
+
StringToNumber.in_numbers('soixante-dix') #=> 70
|
69
|
+
|
70
|
+
# Large numbers
|
71
|
+
StringToNumber.in_numbers('mille deux cent trente-quatre') #=> 1234
|
72
|
+
StringToNumber.in_numbers('un million') #=> 1_000_000
|
73
|
+
StringToNumber.in_numbers('trois milliards') #=> 3_000_000_000
|
74
|
+
|
75
|
+
# Complex expressions
|
76
|
+
StringToNumber.in_numbers('neuf mille neuf cent quatre-vingt-dix-neuf') #=> 9999
|
77
|
+
StringToNumber.in_numbers('deux millions trois cent mille') #=> 2_300_000
|
78
|
+
```
|
79
|
+
|
80
|
+
### Advanced Features
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
# Validation
|
84
|
+
StringToNumber.valid_french_number?('vingt et un') #=> true
|
85
|
+
StringToNumber.valid_french_number?('hello world') #=> false
|
86
|
+
|
87
|
+
# Cache management
|
88
|
+
StringToNumber.clear_caches! # Clear all internal caches
|
89
|
+
stats = StringToNumber.cache_stats
|
90
|
+
puts "Cache hit ratio: #{stats[:cache_hit_ratio]}"
|
91
|
+
|
92
|
+
# Backward compatibility mode
|
93
|
+
StringToNumber.in_numbers('cent', use_optimized: false) #=> 100
|
94
|
+
```
|
95
|
+
|
96
|
+
### Supported Number Formats
|
97
|
+
|
98
|
+
| Range | Examples |
|
99
|
+
|-------|----------|
|
100
|
+
| 0-19 | zéro, un, deux, trois, quatre, cinq, six, sept, huit, neuf, dix, onze, douze, treize, quatorze, quinze, seize, dix-sept, dix-huit, dix-neuf |
|
101
|
+
| 20-99 | vingt, trente, quarante, cinquante, soixante, soixante-dix, quatre-vingts, quatre-vingt-dix |
|
102
|
+
| 100+ | cent, mille, million, milliard, billion |
|
103
|
+
| Compounds | vingt et un, quatre-vingt-quatorze, deux mille trois |
|
104
|
+
|
105
|
+
## ⚡ Performance Tips
|
106
|
+
|
107
|
+
1. **Reuse conversions**: The gem automatically caches results for better performance
|
108
|
+
2. **Batch processing**: Use the optimized parser (default) for better throughput
|
109
|
+
3. **Memory management**: Call `clear_caches!` periodically if processing many unique inputs
|
110
|
+
4. **Thread safety**: The gem is thread-safe and can be used in concurrent environments
|
111
|
+
|
112
|
+
## 🧪 Development
|
113
|
+
|
114
|
+
After checking out the repo, run `bin/setup` to install dependencies:
|
115
|
+
|
116
|
+
```bash
|
117
|
+
$ git clone https://github.com/FabienPiette/string_to_number.git
|
118
|
+
$ cd string_to_number
|
119
|
+
$ bin/setup
|
120
|
+
```
|
28
121
|
|
29
|
-
|
30
|
-
#=> 19
|
122
|
+
### Running Tests
|
31
123
|
|
32
|
-
|
33
|
-
|
124
|
+
```bash
|
125
|
+
# Run all tests
|
126
|
+
$ rake spec
|
34
127
|
|
35
|
-
|
36
|
-
|
128
|
+
# Run performance tests
|
129
|
+
$ ruby benchmark.rb
|
37
130
|
|
38
|
-
|
39
|
-
|
131
|
+
# Run specific test files
|
132
|
+
$ rspec spec/string_to_number_spec.rb
|
40
133
|
```
|
41
134
|
|
42
|
-
|
135
|
+
### Performance Benchmarking
|
136
|
+
|
137
|
+
```bash
|
138
|
+
# Compare implementations
|
139
|
+
$ ruby performance_comparison.rb
|
140
|
+
|
141
|
+
# Detailed micro-benchmarks
|
142
|
+
$ ruby microbenchmark.rb
|
143
|
+
```
|
144
|
+
|
145
|
+
### Interactive Console
|
146
|
+
|
147
|
+
```bash
|
148
|
+
$ bin/console
|
149
|
+
# => Interactive prompt for experimentation
|
150
|
+
```
|
151
|
+
|
152
|
+
## 🏗️ Architecture
|
153
|
+
|
154
|
+
The gem uses a dual-architecture approach:
|
155
|
+
|
156
|
+
- **Optimized Parser** (`StringToNumber::Parser`): High-performance implementation with caching
|
157
|
+
- **Original Implementation** (`StringToNumber::ToNumber`): Reference implementation for compatibility
|
158
|
+
|
159
|
+
Key performance optimizations:
|
160
|
+
- Pre-compiled regex patterns
|
161
|
+
- LRU caching with thread-safe access
|
162
|
+
- Memoized parser instances
|
163
|
+
- Zero-allocation number matching
|
164
|
+
|
165
|
+
## 🤝 Contributing
|
166
|
+
|
167
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/FabienPiette/string_to_number.
|
168
|
+
|
169
|
+
### Development Process
|
170
|
+
|
171
|
+
1. Fork the repository
|
172
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
173
|
+
3. Write tests for your changes
|
174
|
+
4. Ensure all tests pass (`rake spec`)
|
175
|
+
5. Run performance tests to avoid regressions
|
176
|
+
6. Commit your changes (`git commit -am 'Add amazing feature'`)
|
177
|
+
7. Push to the branch (`git push origin feature/amazing-feature`)
|
178
|
+
8. Open a Pull Request
|
179
|
+
|
180
|
+
### Code of Conduct
|
181
|
+
|
182
|
+
This project is intended to be a safe, welcoming space for collaboration. Contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
183
|
+
|
184
|
+
## 📋 Requirements
|
185
|
+
|
186
|
+
- Ruby 2.5 or higher
|
187
|
+
- No external dependencies (uses only Ruby standard library)
|
188
|
+
|
189
|
+
## 🐛 Troubleshooting
|
190
|
+
|
191
|
+
### Common Issues
|
192
|
+
|
193
|
+
**Q: Numbers aren't parsing correctly**
|
194
|
+
A: Ensure your input uses proper French number words. Use `valid_french_number?` to validate input.
|
195
|
+
|
196
|
+
**Q: Performance seems slow**
|
197
|
+
A: Make sure you're using the default optimized parser. Check cache statistics with `cache_stats`.
|
43
198
|
|
44
|
-
|
199
|
+
**Q: Memory usage is high**
|
200
|
+
A: Call `clear_caches!` periodically if processing many unique number strings.
|
45
201
|
|
46
|
-
|
202
|
+
## 📝 Changelog
|
47
203
|
|
48
|
-
|
204
|
+
See [CHANGELOG.md](CHANGELOG.md) for version history and updates.
|
49
205
|
|
50
|
-
|
206
|
+
## 📄 License
|
51
207
|
|
208
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
52
209
|
|
53
|
-
##
|
210
|
+
## 🙏 Acknowledgments
|
54
211
|
|
55
|
-
|
212
|
+
- Original implementation by [Fabien Piette](https://github.com/FabienPiette)
|
213
|
+
- Performance optimizations and enhancements
|
214
|
+
- Community contributors and testers
|
56
215
|
|
data/Rakefile
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'bundler/gem_tasks'
|
2
4
|
require 'rspec/core/rake_task'
|
5
|
+
require 'rubocop/rake_task'
|
3
6
|
|
4
7
|
RSpec::Core::RakeTask.new(:spec)
|
8
|
+
RuboCop::RakeTask.new
|
5
9
|
|
6
|
-
task default:
|
10
|
+
task default: %i[rubocop spec]
|
7
11
|
|
8
12
|
task :env, [:env] do |_t, _args|
|
9
13
|
require 'string_to_number'
|