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; }
/* * 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); }
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; }