2013-06-25 6 views
2

Есть ли эффективный (для текстовых файлов> 5 МБ) цитируемый печатный декодер, написанный на C? Мне нужен такой декодер в проекте iOS.Objective-C decode quoted printable text

В то же время я использую декодер высокого уровня, который слишком медленный. Она занимает до 10 минут на устройстве, чтобы декодировать 5MB файл:

- (NSString *)decodedQuotedPrintable:(NSString *)string 
{ 
    NSMutableString *decodedString = string.mutableCopy; 

    [decodedString replaceOccurrencesOfString:@"=\r\n" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, decodedString.length)]; 

    NSInteger idx = 0; 
    _WHILE(idx != NSNotFound) 
    { 
     idx = [decodedString rangeOfString:@"=" 
            options:NSCaseInsensitiveSearch 
            range:NSMakeRange(idx + 1, decodedString.length - idx - 1)].location; 

     _IF(idx + 5> decodedString.length) 
     { 
      break; 
     } 
     unsigned int hex = 0; 
     NSScanner *scanner = [NSScanner scannerWithString:[decodedString substringWithRange: 
                  NSMakeRange(idx+1, 2)]]; 

     [scanner scanHexInt:&hex]; 

     [decodedString replaceCharactersInRange:NSMakeRange(idx, 3) 
            withString:[NSString stringWithFormat:@"%c", hex]]; 

    } 

    return decodedString; 
} 

ответ

2

У меня есть это сейчас, используя манипуляции с C-Level. Отлично работает. Это уменьшило время обработки тестового файла с 6 минут до 3 секунд на iPad2:

- (char *)replace1:(char const * const)original 
{ 
    char const * const pattern = "=\r\n"; 

    size_t const patlen = strlen(pattern); 
    size_t const orilen = strlen(original); 

    size_t patcnt = 0; 
    const char * oriptr; 
    const char * patloc; 

    // find how many times the pattern occurs in the original string 
    _FOR(oriptr = original; 
     (patloc = strstr(oriptr, pattern)); 
     oriptr = patloc + patlen) 
    { 
     patcnt++; 
    } 

    { 
     // allocate memory for the new string 
     size_t const retlen = orilen - patcnt * patlen; 
     char * const returned = (char *) malloc(sizeof(char) * (retlen + 1)); 

     _IF(returned != NULL) 
     { 
      // copy the original string, 
      // replacing all the instances of the pattern 
      char * retptr = returned; 
      _FOR(oriptr = original; 
       (patloc = strstr(oriptr, pattern)); 
       oriptr = patloc + patlen) 
      { 
       size_t const skplen = patloc - oriptr; 
       // copy the section until the occurence of the pattern 
       strncpy(retptr, oriptr, skplen); 
       retptr += skplen; 
      } 
      // copy the rest of the string. 
      strcpy(retptr, oriptr); 
     } 
     return returned; 
    } 
} 

- (char *)replace2:(char const * const)original 
{ 
    size_t const replen = 1; 
    size_t const patlen = 3; 
    size_t const orilen = strlen(original); 

    size_t patcnt = 0; 
    const char * oriptr; 
    const char * patloc; 

    // find how many times the pattern occurs in the original string 
    _FOR(oriptr = original; (patloc = strstr(oriptr, "=")); oriptr = patloc + patlen) 
    { 
     patcnt++; 
    } 

    { 
     // allocate memory for the new string 
     size_t const retlen = orilen + patcnt * (replen - patlen); 
     char * const returned = (char *) malloc(sizeof(char) * (retlen + 1)); 

     _IF(returned != NULL) 
     { 
      // copy the original string, 
      // replacing all the instances of the pattern 
      char * retptr = returned; 
      _FOR(oriptr = original; 
       (patloc = strstr(oriptr, "=")); 
       oriptr = patloc + patlen) 
      { 
       char newRep[3]; 

       newRep[0] = patloc[1]; 
       newRep[1] = patloc[2]; 
       newRep[2] = '\0'; 

       char _rep[2]; 
       _rep[0] = (char)(int)strtol(newRep, NULL, 16); 
       _rep[1] = '\0'; 

       size_t const skplen = patloc - oriptr; 
       // copy the section until the occurence of the pattern 
       strncpy(retptr, oriptr, skplen); 
       retptr += skplen; 
       // copy the replacement 
       strncpy(retptr, _rep, replen); 
       retptr += replen; 
      } 
      // copy the rest of the string. 
      strcpy(retptr, oriptr); 
     } 
     return returned; 
    } 
} 

- (NSString *)decodedQuotedPrintable:(NSString *)string 
{ 
    char *temp = [self replace1:(char *)[string UTF8String]]; 

    temp = [self replace2:temp]; 

    return [NSString stringWithCString:temp 
           encoding:NSUTF8StringEncoding]; 
} 
1

Старайтесь не делать всю эту манипуляцию в изменяемой строке (которая станет патологическим укорочением строки, один символа за один раз).

Используйте новую строку (или буфер), проанализируйте оригинал, напишите в новый.

+0

Мои мысли точно! Создайте новую изменяемую строку, используя 'stringWithCapacity: [oldString length]]'. Его непонятно, может ли он быстрее получить char * ptr исходным смещениям и читать байты один за другим или задать строку для characterAtIndex - посмотрите сами. –