#ifndef V8_INTL_SUPPORT
#error Internationalization is expected to be enabled.
#endif
#include "src/objects/js-segmenter.h"
#include <map>
#include <memory>
#include <string>
#include "src/execution/isolate.h"
#include "src/heap/factory.h"
#include "src/objects/intl-objects.h"
#include "src/objects/js-segmenter-inl.h"
#include "src/objects/managed-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/option-utils.h"
#include "unicode/brkiter.h"
namespace v8 {
namespace internal {
MaybeDirectHandle<JSSegmenter> JSSegmenter::New(
Isolate* isolate, DirectHandle<Map> map, DirectHandle<Object> locales,
DirectHandle<Object> input_options, const char* service) {
Maybe<std::vector<std::string>> maybe_requested_locales =
Intl::CanonicalizeLocaleList(isolate, locales);
MAYBE_RETURN(maybe_requested_locales, DirectHandle<JSSegmenter>());
std::vector<std::string> requested_locales =
maybe_requested_locales.FromJust();
DirectHandle<JSReceiver> options;
ASSIGN_RETURN_ON_EXCEPTION(isolate, options,
GetOptionsObject(isolate, input_options, service));
Maybe<Intl::MatcherOption> maybe_locale_matcher =
Intl::GetLocaleMatcher(isolate, options, service);
MAYBE_RETURN(maybe_locale_matcher, MaybeDirectHandle<JSSegmenter>());
Intl::MatcherOption matcher = maybe_locale_matcher.FromJust();
Intl::ResolvedLocale r;
if (!Intl::ResolveLocale(isolate, JSSegmenter::GetAvailableLocales(),
requested_locales, matcher, {})
.To(&r)) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError));
}
DirectHandle<String> locale_str =
isolate->factory()->NewStringFromAsciiChecked(r.locale.c_str());
Maybe<Granularity> maybe_granularity = GetStringOption<Granularity>(
isolate, options, isolate->factory()->granularity_string(), service,
std::to_array<const std::string_view>({"grapheme", "word", "sentence"}),
std::array{Granularity::GRAPHEME, Granularity::WORD,
Granularity::SENTENCE},
Granularity::GRAPHEME);
MAYBE_RETURN(maybe_granularity, MaybeDirectHandle<JSSegmenter>());
Granularity granularity_enum = maybe_granularity.FromJust();
icu::Locale icu_locale = r.icu_locale;
DCHECK(!icu_locale.isBogus());
UErrorCode status = U_ZERO_ERROR;
std::unique_ptr<icu::BreakIterator> icu_break_iterator;
switch (granularity_enum) {
case Granularity::GRAPHEME:
icu_break_iterator.reset(
icu::BreakIterator::createCharacterInstance(icu_locale, status));
break;
case Granularity::WORD:
icu_break_iterator.reset(
icu::BreakIterator::createWordInstance(icu_locale, status));
break;
case Granularity::SENTENCE:
icu_break_iterator.reset(
icu::BreakIterator::createSentenceInstance(icu_locale, status));
break;
}
DCHECK(U_SUCCESS(status));
DCHECK_NOT_NULL(icu_break_iterator.get());
DirectHandle<Managed<icu::BreakIterator>> managed_break_iterator =
Managed<icu::BreakIterator>::From(isolate, 0,
std::move(icu_break_iterator));
DirectHandle<JSSegmenter> segmenter =
Cast<JSSegmenter>(isolate->factory()->NewFastOrSlowJSObjectFromMap(map));
DisallowGarbageCollection no_gc;
segmenter->set_flags(0);
segmenter->set_locale(*locale_str);
segmenter->set_granularity(granularity_enum);
segmenter->set_icu_break_iterator(*managed_break_iterator);
return segmenter;
}
DirectHandle<JSObject> JSSegmenter::ResolvedOptions(
Isolate* isolate, DirectHandle<JSSegmenter> segmenter) {
Factory* factory = isolate->factory();
DirectHandle<JSObject> result =
factory->NewJSObject(isolate->object_function());
DirectHandle<String> locale(segmenter->locale(), isolate);
JSObject::AddProperty(isolate, result, factory->locale_string(), locale,
NONE);
JSObject::AddProperty(isolate, result, factory->granularity_string(),
segmenter->GranularityAsString(isolate), NONE);
return result;
}
Handle<String> JSSegmenter::GranularityAsString(Isolate* isolate) const {
return GetGranularityString(isolate, granularity());
}
Handle<String> JSSegmenter::GetGranularityString(Isolate* isolate,
Granularity granularity) {
Factory* factory = isolate->factory();
switch (granularity) {
case Granularity::GRAPHEME:
return factory->grapheme_string();
case Granularity::WORD:
return factory->word_string();
case Granularity::SENTENCE:
return factory->sentence_string();
}
UNREACHABLE();
}
const std::set<std::string>& JSSegmenter::GetAvailableLocales() {
return Intl::GetAvailableLocales();
}
}
}