Пример #1
0
static int expand_variables_internal(parser_t &parser, wchar_t * const in, std::vector<completion_t> &out, long last_idx)
{
    int is_ok= 1;
    int empty=0;

    wcstring var_tmp;
    std::vector<long> var_idx_list;

    //  CHECK( out, 0 );

    for (long i=last_idx; (i>=0) && is_ok && !empty; i--)
    {
        const wchar_t c = in[i];
        if ((c == VARIABLE_EXPAND) || (c == VARIABLE_EXPAND_SINGLE))
        {
            long start_pos = i+1;
            long stop_pos;
            long var_len;
            int is_single = (c==VARIABLE_EXPAND_SINGLE);

            stop_pos = start_pos;

            while (1)
            {
                if (!(in[stop_pos ]))
                    break;
                if (!(iswalnum(in[stop_pos]) ||
                        (wcschr(L"_", in[stop_pos])!= 0)))
                    break;

                stop_pos++;
            }

            /*      printf( "Stop for '%c'\n", in[stop_pos]);*/

            var_len = stop_pos - start_pos;

            if (var_len == 0)
            {
                expand_variable_error(parser, in, stop_pos-1, -1);

                is_ok = 0;
                break;
            }

            var_tmp.append(in + start_pos, var_len);
            env_var_t var_val = expand_var(var_tmp.c_str());

            if (! var_val.missing())
            {
                int all_vars=1;
                wcstring_list_t var_item_list;

                if (is_ok)
                {
                    tokenize_variable_array(var_val.c_str(), var_item_list);

                    if (in[stop_pos] == L'[')
                    {
                        wchar_t *slice_end;
                        all_vars=0;

                        if (parse_slice(in + stop_pos, &slice_end, var_idx_list, var_item_list.size()))
                        {
                            parser.error(SYNTAX_ERROR,
                                         -1,
                                         L"Invalid index value");
                            is_ok = 0;
                            break;
                        }
                        stop_pos = (slice_end-in);
                    }

                    if (!all_vars)
                    {
                        wcstring_list_t string_values(var_idx_list.size());

                        for (size_t j=0; j<var_idx_list.size(); j++)
                        {
                            long tmp = var_idx_list.at(j);
                            /*
                                           Check that we are within array
                                           bounds. If not, truncate the list to
                                           exit.
                                           */
                            if (tmp < 1 || (size_t)tmp > var_item_list.size())
                            {
                                parser.error(SYNTAX_ERROR,
                                             -1,
                                             ARRAY_BOUNDS_ERR);
                                is_ok=0;
                                var_idx_list.resize(j);
                                break;
                            }
                            else
                            {
                                /* Replace each index in var_idx_list inplace with the string value at the specified index */
                                //al_set( var_idx_list, j, wcsdup((const wchar_t *)al_get( &var_item_list, tmp-1 ) ) );
                                string_values.at(j) = var_item_list.at(tmp-1);
                            }
                        }

                        // string_values is the new var_item_list
                        var_item_list.swap(string_values);
                    }
                }

                if (is_ok)
                {

                    if (is_single)
                    {
                        in[i]=0;
                        wcstring res = in;
                        res.push_back(INTERNAL_SEPARATOR);

                        for (size_t j=0; j<var_item_list.size(); j++)
                        {
                            const wcstring &next = var_item_list.at(j);
                            if (is_ok)
                            {
                                if (j != 0)
                                    res.append(L" ");
                                res.append(next);
                            }
                        }
                        res.append(in + stop_pos);
                        is_ok &= expand_variables2(parser, res, out, i);
                    }
                    else
                    {
                        for (size_t j=0; j<var_item_list.size(); j++)
                        {
                            const wcstring &next = var_item_list.at(j);
                            if (is_ok && (i == 0) && (!in[stop_pos]))
                            {
                                append_completion(out, next);
                            }
                            else
                            {

                                if (is_ok)
                                {
                                    wcstring new_in;

                                    if (start_pos > 0)
                                        new_in.append(in, start_pos - 1);

                                    // at this point new_in.size() is start_pos - 1
                                    if (start_pos>1 && new_in[start_pos-2]!=VARIABLE_EXPAND)
                                    {
                                        new_in.push_back(INTERNAL_SEPARATOR);
                                    }
                                    new_in.append(next);
                                    new_in.append(in + stop_pos);
                                    is_ok &= expand_variables2(parser, new_in, out, i);
                                }
                            }

                        }
                    }
                }

                return is_ok;
            }
            else
            {
                /*
                         Expand a non-existing variable
                         */
                if (c == VARIABLE_EXPAND)
                {
                    /*
                               Regular expansion, i.e. expand this argument to nothing
                               */
                    empty = 1;
                }
                else
                {
                    /*
                               Expansion to single argument.
                               */
                    wcstring res;
                    in[i] = 0;
                    res.append(in);
                    res.append(in + stop_pos);

                    is_ok &= expand_variables2(parser, res, out, i);
                    return is_ok;
                }
            }


        }
    }

    if (!empty)
    {
        append_completion(out, in);
    }

    return is_ok;
}
int
SOP_PrimGroupCentroid::buildCentroids(fpreal t, int mode, int method)
{
    bool                        store;
    exint                       int_value;

    const GA_AIFStringTuple     *ident_t;
    GA_Attribute                *ident_attrib;
    GA_Offset                   ptOff;
    GA_RWAttributeRef           ident_gah;
    GA_RWHandleI                class_h;

    const GU_Detail             *input_geo;

    UT_BoundingBox              bbox;
    UT_String                   attr_name, pattern, str_value;
    UT_Vector3                  pos;

    UT_Array<GA_Range>          range_array;
    UT_Array<GA_Range>::const_iterator  array_it;
    UT_StringArray              string_values;
    UT_IntArray                 int_values;

    // Get the input geometry as read only.
    GU_DetailHandleAutoReadLock gdl(inputGeoHandle(0));
    input_geo = gdl.getGdp();

    // Check to see if we should store the source group/attribute name as an
    // attribute the generated points.
    store = STORE(t);

    // If we want to we need to create the attributes.
    if (store)
    {
        // A 'class' operation, so create a new integer attribute.
        if (mode == 2)
        {
            // Add the int tuple.
            ident_gah = gdp->addIntTuple(GA_ATTRIB_POINT, "class", 1);
            // Bind the handle.
            class_h.bind(ident_gah.getAttribute());
        }
        // Using the 'name' attribute or groups, so create a new string
        // attribute.
        else
        {
            attr_name = (mode == 0) ? "group" : "name";

            // Create a new string attribute.
            ident_gah = gdp->addStringTuple(GA_ATTRIB_POINT, attr_name, 1);
            ident_attrib = ident_gah.getAttribute();

            // Get the string tuple so we can set values.
            ident_t = ident_gah.getAIFStringTuple();
        }
    }

    // Create a new attribute reference map.
    GA_AttributeRefMap          hmap(*gdp, input_geo);

    // Get the attribute selection string.
    ATTRIBUTES(pattern, t);

    // If we have a pattern, try to build the ref map.
    if (pattern.length() > 0)
        buildRefMap(hmap, pattern, gdp, input_geo, mode, GA_ATTRIB_PRIMITIVE);

    // The list of GA_Primitives in the input geometry.
    const GA_PrimitiveList &prim_list = input_geo->getPrimitiveList();

    // Creating by groups.
    if (mode == 0)
    {
        // Get the group pattern.
        GROUP(pattern, t);

        // If the group string is empty, get out of here.
        if (pattern.length() == 0)
            return 1;

        buildGroupData(pattern, input_geo, range_array, string_values);
    }
    // 'name' or 'class'.
    else
    {
        // Build the data.  If something failed, return that we had an issue.
        if (buildAttribData(mode, input_geo, range_array, string_values, int_values))
            return 1;
    }

    // Iterate over each of the primitive ranges we found.
    for (array_it=range_array.begin(); !array_it.atEnd(); ++array_it)
    {
        // Create a new point.
        ptOff = gdp->appendPointOffset();

        // Bounding Box
        if (method == 1)
        {
            // Calculate the bouding box center for this range.
            boundingBox(input_geo, *array_it, prim_list, pos);
            // Set the point's position to the center of the box.
            gdp->setPos3(ptOff, pos);
        }
        // Center of Mass
        else if (method == 2)
        {
            // Calculate the center of mass for this range.
            centerOfMass(*array_it, prim_list, pos);
            // Set the point's position to the center of mass.
            gdp->setPos3(ptOff, pos);
        }
        // Barycenter
        else
        {
            // Calculate the barycenter for this range.
            baryCenter(input_geo, *array_it, prim_list, pos);
            // Set the point's position to the barycenter.
            gdp->setPos3(ptOff, pos);
        }

        // Store the source value if required.
        if (store)
        {
            // 'class', so get the integer value at this iterator index.
            if (mode == 2)
            {
                int_value = int_values(array_it.index());
                class_h.set(ptOff, int_value);
            }
            // 'name' or by group, so get the string value at this iterator
            // index.
            else
            {
                str_value = string_values(array_it.index());
                ident_t->setString(ident_attrib, ptOff, str_value, 0);
            }
        }

        // If there are no entries in the map then we don't need to copy
        // anything.
        if (hmap.entries() > 0)
        {
            GA_WeightedSum              sum;

            // Start a weighted sum for the range.
            hmap.startSum(sum, GA_ATTRIB_POINT, ptOff);

            // Add the values for each primitive to the sum.
            for (GA_Iterator it(*array_it); !it.atEnd(); ++it)
            {
                hmap.addSumValue(sum,
                                 GA_ATTRIB_POINT,
                                 ptOff,
                                 GA_ATTRIB_PRIMITIVE,
                                 *it,
                                 1);
            }

            // Finish the sum, normalizing the values.
            hmap.finishSum(sum,
                           GA_ATTRIB_POINT,
                           ptOff,
                           1.0/(*array_it).getEntries());
        }
    }

    return 0;
}