in src/core/storage/sframe_interface/unity_sarray.cpp [1372:1494]
std::shared_ptr<unity_sarray_base> unity_sarray::lazy_astype(flex_type_enum dtype,
bool undefined_on_failure) {
log_func_entry();
flex_type_enum current_type = this->dtype();
// Special path for converting image sarray to vector type.
if (current_type == flex_type_enum::IMAGE &&
dtype == flex_type_enum::VECTOR) {
return image_util::image_sarray_to_vector_sarray(
std::static_pointer_cast<unity_sarray>(shared_from_this()),
undefined_on_failure);
}
// Special path for converting strings to image
if (current_type == flex_type_enum::STRING &&
dtype == flex_type_enum::IMAGE) {
return transform_lambda([=](const flexible_type& f)->flexible_type {
try {
return image_util::load_image(f.to<flex_string>(), "");
} catch (...) {
if (undefined_on_failure) return FLEX_UNDEFINED;
else throw;
}
},
dtype,
true /*skip undefined*/,
0 /*random seed*/);
};
// if no changes. just keep the identity function
if (dtype == current_type) {
return std::static_pointer_cast<unity_sarray>(shared_from_this());
}
if(! (flex_type_is_convertible(current_type, dtype) ||
(current_type == flex_type_enum::STRING && dtype == flex_type_enum::INTEGER) ||
(current_type == flex_type_enum::STRING && dtype == flex_type_enum::FLOAT) ||
(current_type == flex_type_enum::STRING && dtype == flex_type_enum::VECTOR) ||
(current_type == flex_type_enum::STRING && dtype == flex_type_enum::LIST) ||
(current_type == flex_type_enum::STRING && dtype == flex_type_enum::DICT) ||
(current_type == flex_type_enum::LIST && dtype == flex_type_enum::VECTOR)
)) {
log_and_throw("Not able to cast to given type");
}
// The assigment operator takes care of casting
if (current_type == flex_type_enum::STRING) {
flexible_type_parser parser;
// we need to treat strings with special care
// we need to perform a lexical cast
auto transform_fn = [dtype,undefined_on_failure,parser]
(const flexible_type& f)mutable ->flexible_type {
if (f.get_type() == flex_type_enum::UNDEFINED) return f;
flexible_type ret;
try {
if (dtype == flex_type_enum::INTEGER) {
ret = f.to<flex_int>();
} else if (dtype == flex_type_enum::FLOAT) {
ret = f.to<flex_float>();
} else if (dtype == flex_type_enum::VECTOR) {
bool success;
const std::string& val = f.get<flex_string>();
const char* c = val.c_str();
std::tie(ret, success) = parser.vector_parse(&c, val.length());
if (!success) {
if (undefined_on_failure) ret = FLEX_UNDEFINED;
else log_and_throw("Cannot convert to array");
}
} else if (dtype == flex_type_enum::LIST) {
bool success;
const std::string& val = f.get<flex_string>();
const char* c = val.c_str();
std::tie(ret, success) = parser.recursive_parse(&c, val.length());
if (!success) {
if (undefined_on_failure) ret = FLEX_UNDEFINED;
else log_and_throw("Cannot convert to list");
}
} else if (dtype == flex_type_enum::DICT) {
bool success;
const std::string& val = f.get<flex_string>();
const char* c = val.c_str();
std::tie(ret, success) = parser.dict_parse(&c, val.length());
if (!success) {
if (undefined_on_failure) ret = FLEX_UNDEFINED;
else log_and_throw("Cannot convert to dict");
}
}
} catch(const std::string& s) {
if (undefined_on_failure) ret = FLEX_UNDEFINED;
else log_and_throw("Unable to interpret value of \"" + f.get<flex_string>()
+ "\" as a " + flex_type_enum_to_name(dtype) + ".");
} catch(const std::exception& s) {
if (undefined_on_failure) ret = FLEX_UNDEFINED;
else log_and_throw("Unable to interpret value of \"" + f.get<flex_string>()
+ "\" as a " + flex_type_enum_to_name(dtype) + ".");
}
return ret;
};
auto ret = transform_lambda(transform_fn,
dtype,
true /*skip undefined*/,
0 /*random seed*/);
return ret;
} else {
auto ret = transform_lambda([dtype, undefined_on_failure](const flexible_type& f)->flexible_type {
flexible_type ret(dtype);
try {
ret.soft_assign(f);
} catch (...) {
if (undefined_on_failure) return FLEX_UNDEFINED;
else throw;
}
return ret;
},
dtype,
true /*skip undefined*/,
0 /*random seed*/);
return ret;
}
}