Skip to content
Snippets Groups Projects
Forked from Alchemy Viewer / Alchemy Viewer
Source project has a limited visibility.
  • Nat Goodspeed's avatar
    f7d2d40b
    DRTVWR-587: Fix LL::apply(function, LLSD array). · f7d2d40b
    Nat Goodspeed authored
    We define a specialization of LLSDParam<const char*> to support passing an
    LLSD object to a const char* function parameter. Needless to remark, passing
    object.asString().c_str() would be Bad: destroying the temporary std::string
    returned by asString() would immediately invalidate the pointer returned by
    its c_str(). But when you pass LLSDParam<const char*>(object) as the
    parameter, that specialization itself stores the std::string so the c_str()
    pointer remains valid as long as the LLSDParam object does.
    
    Then there's LLSDParam<LLSD>, used when we don't have the parameter type
    available to select the LLSDParam specialization. LLSDParam<LLSD> defines a
    templated conversion operator T() that constructs an LLSDParam<T> to provide
    the actual parameter value. So far, so good.
    
    The trouble was with the implementation of LLSDParam<LLSD>: it constructed a
    _temporary_ LLSDParam<T>, implicitly called its operator T() and immediately
    destroyed it. Destroying LLSDParam<const char*> destroyed its stored string,
    thus invalidating the c_str() pointer before the target function was entered.
    
    Instead, make LLSDParam<LLSD>::operator T() capture each LLSDParam<T> it
    constructs, extending its lifespan to the lifespan of the LLSDParam<LLSD>
    instance. For this, derive each LLSDParam specialization from LLSDParamBase, a
    trivial base class that simply establishes the virtual destructor. We can then
    capture any specialization as a pointer to LLSDParamBase.
    
    Also restore LazyEventAPI tests on Mac.
    f7d2d40b
    History
    DRTVWR-587: Fix LL::apply(function, LLSD array).
    Nat Goodspeed authored
    We define a specialization of LLSDParam<const char*> to support passing an
    LLSD object to a const char* function parameter. Needless to remark, passing
    object.asString().c_str() would be Bad: destroying the temporary std::string
    returned by asString() would immediately invalidate the pointer returned by
    its c_str(). But when you pass LLSDParam<const char*>(object) as the
    parameter, that specialization itself stores the std::string so the c_str()
    pointer remains valid as long as the LLSDParam object does.
    
    Then there's LLSDParam<LLSD>, used when we don't have the parameter type
    available to select the LLSDParam specialization. LLSDParam<LLSD> defines a
    templated conversion operator T() that constructs an LLSDParam<T> to provide
    the actual parameter value. So far, so good.
    
    The trouble was with the implementation of LLSDParam<LLSD>: it constructed a
    _temporary_ LLSDParam<T>, implicitly called its operator T() and immediately
    destroyed it. Destroying LLSDParam<const char*> destroyed its stored string,
    thus invalidating the c_str() pointer before the target function was entered.
    
    Instead, make LLSDParam<LLSD>::operator T() capture each LLSDParam<T> it
    constructs, extending its lifespan to the lifespan of the LLSDParam<LLSD>
    instance. For this, derive each LLSDParam specialization from LLSDParamBase, a
    trivial base class that simply establishes the virtual destructor. We can then
    capture any specialization as a pointer to LLSDParamBase.
    
    Also restore LazyEventAPI tests on Mac.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.