예제 #1
0
replace_delete_single_character(PyStringObject *self,
                                char from_c, Py_ssize_t maxcount)
{
    char *self_s, *result_s;
    char *start, *next, *end;
    Py_ssize_t self_len, result_len;
    Py_ssize_t count;
    PyStringObject *result;

    self_len = PyString_GET_SIZE(self);
    self_s = PyString_AS_STRING(self);

    count = countchar(self_s, self_len, from_c, maxcount);
    if (count == 0) {
        return return_self(self);
    }

    result_len = self_len - count;  /* from_len == 1 */
    assert(result_len>=0);

    if ( (result = (PyStringObject *)
                    PyString_FromStringAndSize(NULL, result_len)) == NULL)
        return NULL;
    result_s = PyString_AS_STRING(result);

    start = self_s;
    end = self_s + self_len;
    while (count-- > 0) {
        next = findchar(start, end-start, from_c);
        if (next == NULL)
            break;
        Py_MEMCPY(result_s, start, next-start);
        result_s += (next-start);
        start = next+1;
    }
    Py_MEMCPY(result_s, start, end-start);

    return result;
}
예제 #2
0
/*
 * insert_mount_point: insert a mount point into config (mnt_pts).
 *
 * @param pconf the current config
 * @param pmnt the mount point to try and insert
 * @return NULL on success, otherwise an error message string
 */
string *
insert_mount_point(PlfsConf *pconf, PlfsMount *pmnt)
{
    /*
     * two main mallocs here:
     *
     * struct plfs_backend *backstore
     *
     *    there is one struct per backend physical path in plfsrc
     *    allocated here, starting with "backends" then
     *    "canonical_backends" and finally "shadow_backends"
     * 
     * struct plfs_backends **bpa
     *
     *    an array of backend pointers that eventually get broken
     *    up into the PlfsMount's backends, canonical_backends, and
     *    shadow_backends.  this indirection allows a single backend
     *    from backstore to appear in more than one of PlfsMount's
     *    lists.
     *
     * simple example: if plfsrc has 
     *
     * "backends /m/vol0/plfs,/m/vol1/plfs"
     *
     * and no "canonical_backends" or "shadow_backends" set, then
     * backstore will have two entries (for vol0 and vol1) and the
     * size of bpa will be 6, as vol0/vol1 will appear in all three
     * lists (backends, canonical_backends, shadow_backends) and 3*2
     * == 6.  so each entry in backstore will be pointed to multiple
     * times (3 times).
     */
    string *error;
    int backspeccnt, canspeccnt, shadowspeccnt;  /* plfsrc counts */
    int backsoff, cansoff, shadsoff;             /* offset in backstore[] */
    int backptroff, canptroff, shadowptroff;     /* offset in bpa[] */
    int lcv;                    /* loop control variable */
    struct plfs_backend **bpa;  /* backpointer array */
    pair<map<string,PlfsMount *>::iterator, bool> insert_ret;

    /* this makes use of countchar() returning -1 if string is NULL */
    backspeccnt = countchar(',', pmnt->backspec) + 1;
    canspeccnt = countchar(',', pmnt->canspec) + 1;
    shadowspeccnt = countchar(',', pmnt->shadowspec) + 1;

    /*
     * backspec backends will be referenced from all 3 arrays.
     * canspec and shadowspec backends will be referenced from 2 arrays.
     */
    pmnt->nback       = backspeccnt + canspeccnt + shadowspeccnt;
    pmnt->ncanback    = backspeccnt + canspeccnt;
    pmnt->nshadowback = backspeccnt + shadowspeccnt;
    /*
     * quick sanity check.   what else should we check?
     */
    if (pmnt->nback == 0) { 
        error = new string("no backends for mount: ");
        error->append(pmnt->mnt_pt);
        return(error);
    }

    /*
     * disallow 'backends' to be used with 'canonical_backends' or
     * 'shadow_backends' for now...
     */
    if (backspeccnt != 0 && (canspeccnt || shadowspeccnt)) {
        error = new string("cannot use 'backends' with 'canonical_backends' "
                           "or 'shadow_backends': ");
        error->append(pmnt->mnt_pt);
        return(error);
    }
    
    /*
     * start allocating memory.   backstore is ordered as
     * backspec, canspec, then shadowspec, compute offsets based
     * on that.   bpa has sections for backends (B+C+S),
     * canonical_backends (B+C), and shadow_backends (B+S).
     */
    pmnt->backstore = (struct plfs_backend *)
        calloc(pmnt->nback, sizeof(pmnt->backstore[0]));
    backsoff = 0;
    cansoff = backsoff + backspeccnt;
    shadsoff = cansoff + canspeccnt;

    bpa = (struct plfs_backend **)
        calloc(pmnt->nback + pmnt->ncanback + pmnt->nshadowback,
               sizeof(bpa[0]));
    backptroff = 0;
    canptroff = backptroff + pmnt->nback;
    shadowptroff = canptroff + pmnt->ncanback;
    
    /* ... but malloc could have failed */
    if (pmnt->backstore == NULL || bpa == NULL) {
        if (pmnt->backstore) free(pmnt->backstore);
        if (bpa) free(bpa);
        /* XXX: 'new' does a malloc, likely to fail here too. */
        error = new string("insert_mount_point: backstore malloc failed");
        return(error);
    }
    for (lcv = 0 ; lcv < pmnt->nback ; lcv++) {
        /* placement new to properly init C++ string plfs_backend.path */
        new(&pmnt->backstore[lcv]) plfs_backend;
    }

    /* setup the backstore array */
    if (backspeccnt) {
        if ((error = insert_backends(pconf, pmnt->backspec, backspeccnt,
                                     &pmnt->backstore[backsoff])) != NULL) {
            goto got_error;
        }
    }
    if (canspeccnt) {
        if ((error = insert_backends(pconf, pmnt->canspec, canspeccnt,
                                     &pmnt->backstore[cansoff])) != NULL) {
            goto got_error;
        }
    }
    if (shadowspeccnt) {
        if ((error = insert_backends(pconf, pmnt->shadowspec, shadowspeccnt,
                                     &pmnt->backstore[shadsoff])) != NULL) {
            goto got_error;
        }
    }

    /* now setup the pointer arrays */
    pmnt->backends = bpa + backptroff;
    pmnt->canonical_backends = bpa + canptroff;
    pmnt->shadow_backends = bpa + shadowptroff;

    for (lcv = 0 ; lcv < backspeccnt ; lcv++) {
        pmnt->backends[lcv] = pmnt->canonical_backends[lcv] =
            pmnt->shadow_backends[lcv] = &pmnt->backstore[lcv];
    }
    for (lcv = 0 ; lcv < canspeccnt ; lcv++) {
        pmnt->backends[lcv+backspeccnt] =
            pmnt->canonical_backends[lcv+backspeccnt] =
            &pmnt->backstore[cansoff + lcv];
    }
    for (lcv = 0 ; lcv < shadowspeccnt ; lcv++) {
        pmnt->backends[lcv+backspeccnt+canspeccnt] =
            pmnt->shadow_backends[lcv+backspeccnt] =
            &pmnt->backstore[shadsoff + lcv];
    }

    /* finally, insert into list of global mount points */
    mlog(INT_DCOMMON, "Inserting mount point %s",
         pmnt->mnt_pt.c_str());
    insert_ret = pconf->mnt_pts.insert(pair<string,PlfsMount *>(pmnt->mnt_pt,
                                                                pmnt));
    if (!insert_ret.second) {
        error = new string("mount point multiply defined");
        goto got_error;
    }

    /*
     * done!
     */
    return(NULL);

 got_error:
    free(pmnt->backstore);
    free(bpa);
    return(error);
}
예제 #3
0
replace_single_character(PyStringObject *self,
                         char from_c,
                         const char *to_s, Py_ssize_t to_len,
                         Py_ssize_t maxcount)
{
    char *self_s, *result_s;
    char *start, *next, *end;
    Py_ssize_t self_len, result_len;
    Py_ssize_t count, product;
    PyStringObject *result;

    self_s = PyString_AS_STRING(self);
    self_len = PyString_GET_SIZE(self);

    count = countchar(self_s, self_len, from_c, maxcount);
    if (count == 0) {
        /* no matches, return unchanged */
        return return_self(self);
    }

    /* use the difference between current and new, hence the "-1" */
    /*   result_len = self_len + count * (to_len-1)  */
    product = count * (to_len-1);
    if (product / (to_len-1) != count) {
        PyErr_SetString(PyExc_OverflowError, "replace string is too long");
        return NULL;
    }
    result_len = self_len + product;
    if (result_len < 0) {
        PyErr_SetString(PyExc_OverflowError, "replace string is too long");
        return NULL;
    }

    if ( (result = (PyStringObject *)
          PyString_FromStringAndSize(NULL, result_len)) == NULL)
        return NULL;
    result_s = PyString_AS_STRING(result);

    start = self_s;
    end = self_s + self_len;
    while (count-- > 0) {
        next = findchar(start, end-start, from_c);
        if (next == NULL)
            break;

        if (next == start) {
            /* replace with the 'to' */
            Py_MEMCPY(result_s, to_s, to_len);
            result_s += to_len;
            start += 1;
        } else {
            /* copy the unchanged old then the 'to' */
            Py_MEMCPY(result_s, start, next-start);
            result_s += (next-start);
            Py_MEMCPY(result_s, to_s, to_len);
            result_s += to_len;
            start = next+1;
        }
    }
    /* Copy the remainder of the remaining string */
    Py_MEMCPY(result_s, start, end-start);

    return result;
}