Measurement Formatters & ICU

Hi,

I am new to the mailing list, and am interested in contributing to the swift project.

I’ve been having a play with the ICU library’s unit formatting functions, and have created a simple wrapper that could be used by the various measurement formatters as well as the date component formatter. At the moment, this wrapper is written in swift, but I’m thinking it might make more sense to implement it as a core foundation layer, so as not to expose ICU directly to swift.

The interface for this could look something like:

enum CFUnitFormatterStyle{
    
    CFUnitFormatterStyleLong,
    CFUnitFormatterStyleMedium,
    ...
    
};

enum CFUnitFormatterUnit{
    
    CFUnitFormatterUnit_Length_Meter,
    ...
    CFUnitFormatterUnit_Mass_Gram,
    ...
    
};

struct CFUnitFormatterMeasure{
    
    double value;
    CFUnitFormatterUnit unit;
    
};

CFUnitFormatterRef CFUnitFormatterCreate(CFAllocatorRef allocator, CFLocaleRef locale, CFUnitFormatterStyle style, CFNumberFormatterRef numberFormatter);

CFStringRef CFUnitFormatterCreateString(CFAllocatorRef allocator, CFUnitFormatterRef formatter, double value, CFUnitFormatterUnit unit);

CFStringRef CFUnitFormatterCreateStringWithMeasure(CFAllocatorRef allocator, CFUnitFormatterRef formatter, CFUnitFormatterMeasure measure);

CFStringRef CFUnitFormatterCreateStringWithMeasures(CFAllocatorRef allocator, CFUnitFormatterRef formatter, CFArrayRef measures);

Looking for any thoughts and suggestions before I begin implementing this.

Henry

···

---
Henry Betts
henrybetts.co.uk <http://henrybetts.co.uk/&gt;

Hi Henry,

Hi,

I am new to the mailing list, and am interested in contributing to the swift project.

Welcome!

I’ve been having a play with the ICU library’s unit formatting functions, and have created a simple wrapper that could be used by the various measurement formatters as well as the date component formatter. At the moment, this wrapper is written in swift, but I’m thinking it might make more sense to implement it as a core foundation layer, so as not to expose ICU directly to swift.

The interface for this could look something like:

enum CFUnitFormatterStyle{
    
    CFUnitFormatterStyleLong,
    CFUnitFormatterStyleMedium,
    ...
    
};

enum CFUnitFormatterUnit{
    
    CFUnitFormatterUnit_Length_Meter,
    ...
    CFUnitFormatterUnit_Mass_Gram,
    ...
    
};

struct CFUnitFormatterMeasure{
    
    double value;
    CFUnitFormatterUnit unit;
    
};

CFUnitFormatterRef CFUnitFormatterCreate(CFAllocatorRef allocator, CFLocaleRef locale, CFUnitFormatterStyle style, CFNumberFormatterRef numberFormatter);

CFStringRef CFUnitFormatterCreateString(CFAllocatorRef allocator, CFUnitFormatterRef formatter, double value, CFUnitFormatterUnit unit);

CFStringRef CFUnitFormatterCreateStringWithMeasure(CFAllocatorRef allocator, CFUnitFormatterRef formatter, CFUnitFormatterMeasure measure);

CFStringRef CFUnitFormatterCreateStringWithMeasures(CFAllocatorRef allocator, CFUnitFormatterRef formatter, CFArrayRef measures);

Looking for any thoughts and suggestions before I begin implementing this.

Henry

This approach makes sense - we have been putting stub functions into CF to use ICU, because ICU’s headers are not module-friendly (yet?). Our Darwin implementation also maps to the ICU constants for units (that I’m sure you found).

I would love to be able to use ICU from Swift instead of implementing everything twice, but maybe that’s a tall order.

- Tony

···

On Aug 22, 2016, at 7:00 AM, Henry Betts via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:

It would be great for someone to work with the upstream ICU project to get their headers to be module friendly.

-Chris

···

On Aug 22, 2016, at 10:10 AM, Tony Parker via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:

Looking for any thoughts and suggestions before I begin implementing this.

Henry

This approach makes sense - we have been putting stub functions into CF to use ICU, because ICU’s headers are not module-friendly (yet?). Our Darwin implementation also maps to the ICU constants for units (that I’m sure you found).

I would love to be able to use ICU from Swift instead of implementing everything twice, but maybe that’s a tall order.

I think there is a review related to format APIs ongoing for ICU 58, but there hasn’t been much talk about the C APIs alas:
https://sourceforge.net/p/icu/mailman/message/35283778/
http://bugs.icu-project.org/trac/ticket/12029

Since MeasureFormat ‘and friends’ are C++, for now, I also think the best path would be a C wrapper in CF that can pass things off to Apple’s ICU or on Linux to:
http://opensource.apple.com/source/ICU/ICU-551.30/icuSources/i18n/uameasureformat.cpp
http://opensource.apple.com/source/ICU/ICU-551.30/icuSources/i18n/uatimeunitformat.cpp

I think the script to handle ninja on Linux also needed to be modified to build C++ successfully (I believe some private/internal includes needed to be set).

Regards,
Will Stanton

···

On Aug 22, 2016, at 1:10 PM, Tony Parker via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:

I would love to be able to use ICU from Swift instead of implementing everything twice, but maybe that’s a tall order.

Yes - I was planning on including uameasureformat.cpp for the linux build, although I was also unsure whether the build script was setup to compile c++.
Noticed a bug in uameasureformat.cpp by the way; DURATION_DAY and DURATION_WEEK are the wrong way around!

I’m a bit confused by uatimeunitformat. I’m probably missing something obvious, but what can it do that uameasureformat can’t do?

Henry

···

On 22 Aug 2016, at 19:07, Will Stanton via swift-corelibs-dev <swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@swift.org>> wrote:

Since MeasureFormat ‘and friends’ are C++, for now, I also think the best path would be a C wrapper in CF that can pass things off to Apple’s ICU or on Linux to:
http://opensource.apple.com/source/ICU/ICU-551.30/icuSources/i18n/uameasureformat.cpp
http://opensource.apple.com/source/ICU/ICU-551.30/icuSources/i18n/uatimeunitformat.cpp

---
Henry Betts
henrybetts.co.uk <http://henrybetts.co.uk/&gt;

I recall the time formatter being deprecated in favor of measfmt, so you might be right that uatimeunitformat isn't needed. I think some functions in uatimeunitformat.cpp made combining units easier when calling from (then NS)DateComponentsFormatter, but perhaps that can be put functionality in a (Swift-)CFDateComponentsFormatter wrapper. (Not sure if Apple will come out with its own CFDateComponentsFormatter).

I think this was what I had to change to get C++ working:

The includes for CompileCxx should be more like CompileC.

Regards,
Will Stanton

···

Sent from my iPhone

On Aug 22, 2016, at 15:58, Henry Betts via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:

Yes - I was planning on including uameasureformat.cpp for the linux build, although I was also unsure whether the build script was setup to compile c++.
Noticed a bug in uameasureformat.cpp by the way; DURATION_DAY and DURATION_WEEK are the wrong way around!

I’m a bit confused by uatimeunitformat. I’m probably missing something obvious, but what can it do that uameasureformat can’t do?

+Daphne since she was the one who implemented the Darwin version of the unit and measurements and I think she has some ideas on how we could perhaps build a uniform version for Linux hosts.

Per the C++; the script for that phase probably needs a bit of love since we haven’t had a need for C++ to be built in CF.

Is there a specific version of ICU that we need to pick that functionality up? As it stands we don’t have a upper version limit on ICU but if we had a portion of the ICU source in CF it would probably mean that we would get symbolic conflicts when linking against versions that already had that.

···

On Aug 22, 2016, at 1:36 PM, Will Stanton via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:

I recall the time formatter being deprecated in favor of measfmt, so you might be right that uatimeunitformat isn't needed. I think some functions in uatimeunitformat.cpp made combining units easier when calling from (then NS)DateComponentsFormatter, but perhaps that can be put functionality in a (Swift-)CFDateComponentsFormatter wrapper. (Not sure if Apple will come out with its own CFDateComponentsFormatter).

I think this was what I had to change to get C++ working:
https://github.com/apple/swift-corelibs-foundation/blob/master/lib/phases.py
The includes for CompileCxx should be more like CompileC.

Regards,
Will Stanton

Sent from my iPhone

On Aug 22, 2016, at 15:58, Henry Betts via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:

Yes - I was planning on including uameasureformat.cpp for the linux build, although I was also unsure whether the build script was setup to compile c++.
Noticed a bug in uameasureformat.cpp by the way; DURATION_DAY and DURATION_WEEK are the wrong way around!

I’m a bit confused by uatimeunitformat. I’m probably missing something obvious, but what can it do that uameasureformat can’t do?

_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev

Looks like the C++ MeasureFormat (and friends) have existed since ICU 3.0, although they have not yet got around to implementing a C interface. I don’t think symbolic conflicts would occur, since, if ICU did eventually introduce the C interface, I assume that it would use just a “u” prefix rather than “ua”. Not sure if that’s what you meant.

Alternatively, I suppose we could just bypass uameasureformat, and interact with the c++ api directly in CF, since it looks like it’s going to have to be setup to compile c++ anyway.

Henry

···

On 23 Aug 2016, at 16:58, Philippe Hausler <phausler@apple.com> wrote:

Is there a specific version of ICU that we need to pick that functionality up? As it stands we don’t have a upper version limit on ICU but if we had a portion of the ICU source in CF it would probably mean that we would get symbolic conflicts when linking against versions that already had that.

Just because it was super-easy for me to fix:

That should allow C++ to be built if desired into CoreFoundation. However round tripping that into the Darwin version of CoreFoundation may be a bit cagey.

···

On Aug 23, 2016, at 4:53 PM, Henry Betts <henry.betts@btconnect.com> wrote:

On 23 Aug 2016, at 16:58, Philippe Hausler <phausler@apple.com> wrote:

Is there a specific version of ICU that we need to pick that functionality up? As it stands we don’t have a upper version limit on ICU but if we had a portion of the ICU source in CF it would probably mean that we would get symbolic conflicts when linking against versions that already had that.

Looks like the C++ MeasureFormat (and friends) have existed since ICU 3.0, although they have not yet got around to implementing a C interface. I don’t think symbolic conflicts would occur, since, if ICU did eventually introduce the C interface, I assume that it would use just a “u” prefix rather than “ua”. Not sure if that’s what you meant.

Alternatively, I suppose we could just bypass uameasureformat, and interact with the c++ api directly in CF, since it looks like it’s going to have to be setup to compile c++ anyway.

Henry