/** * Build the segment array by parsing the path. when the path is modified, * the existing map is invalidated and needs to be remapped. */ void parse() { // Already been here? if (segmentCount > 0) return; segmentCount = 0; extraSegments.clear(); if (path.isEmpty()) { // There always has to be at least one segment. allocSegment(&emptyPath); DENG2_ASSERT(segmentCount > 0); return; } QChar const *segBegin = path.constData(); QChar const *segEnd = path.constData() + path.length() - 1; // Skip over any trailing delimiters. for (int i = path.length(); segEnd->unicode() && *segEnd == separator && i-- > 0; --segEnd) {} // Scan the path for segments, in reverse order. QChar const *from; forever { if (segEnd < segBegin) break; // E.g., path is "/" // Find the start of the next segment. for (from = segEnd; from > segBegin && !(*from == separator); from--) {} int startIndex = (*from == separator? from + 1 : from) - path.constData(); int length = (segEnd - path.constData()) - startIndex + 1; allocSegment(QStringRef(&path, startIndex, length)); // Are there no more parent directories? if (from == segBegin) break; // So far so good. Move one directory level upwards. // The next name ends here. segEnd = from - 1; } // Unix style zero-length root name? if (*segBegin == separator) { allocSegment(&emptyPath); } DENG2_ASSERT(segmentCount > 0); }
void Stream::putSegment(int length, const char *ptr, bool copy) { #ifdef ENGINE ASSERT (length >= 0); #endif if (length == 0) return; const char *address = ptr; totalLength += length; if (!segments) { if (copyFlag = copy) { allocSegment (MAX (length, minSegment)); current->length = length; memcpy (current->address, address, length); } else { //copyFlag = copy; current = segments = &first; current->length = length; current->address = (char*) address; current->next = NULL; } } else if (copyFlag) { int l = currentLength - current->length; if (l > 0) { const int l2 = MIN (l, length); memcpy (current->address + current->length, address, l2); current->length += l2; length -= l2; address += l2; } if (length) { allocSegment (MAX (length, minSegment)); current->length = length; memcpy (current->address, address, length); } } else { allocSegment (0); current->address = (char*) address; current->length = length; } }
void Stream::compress(int length, const void * address) { //printShorts ("Original data", (length + 1) / 2, (short*) address); Segment *segment = allocSegment (length + 5); short *q = (short*) segment->address; const short *p = (short*) address; const short* const end = p + (length + 1) / 2; const short* const yellow = end - 2; *q++ = length; while (p < end) { short *start = ++q; while (p < end && (p >= yellow || p[0] != p[1] || p[1] != p[2])) *q++ = *p++; int n = q - start; if (n) start [-1] = -n; else --q; if (p >= end) break; const short* start2 = p++; while (p < end && *p == *start2) ++p; n = p - start2; *q++ = n; *q++ = *start2; } totalLength = segment->length = (char*) q - segment->address; }
void Stream::putCharacter(char c) { if (!segments || current->length >= currentLength) allocSegment (MAX (100, minSegment)); current->address [current->length] = c; ++current->length; ++totalLength; }
void Stream::putSegment(int length, const unsigned short *chars) { if (length == 0) return; totalLength += length; const unsigned short *wc = chars; if (!segments) { allocSegment (MAX (length, minSegment)); current->length = length; } else { int l = currentLength - current->length; if (l > 0) { const int l2 = MIN (l, length); char *p = current->address + current->length; for (int n = 0; n < l2; ++n) *p++ = (char) *wc++; //memcpy (current->address + current->length, address, l2); current->length += l2; length -= l2; //address += l2; } if (length) { allocSegment (MAX (length, minSegment)); current->length = length; //memcpy (current->address, address, length); } } char *p = current->address; for (int n = 0; n < length; ++n) *p++ = (char) *wc++; }
char* Stream::alloc(int length) { totalLength += length; if (!current || length > currentLength - current->length) allocSegment (length); char* const p = current->tail + current->length; current->length += length; return p; }