blob: aca252433e43ef046395a872665465264537e85c [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#import <Foundation/Foundation.h>
#include "DFPlatform.h"
#include "StringTests.h"
#include "DFString.h"
int testDFNextChar(const uint32_t *input32, size_t len32)
{
printf("Testing DFNextChar\n");
NSString *ns = [[NSString alloc] initWithBytes: input32 length: len32*sizeof(uint32_t)
encoding: NSUTF32LittleEndianStringEncoding];
assert(ns != nil);
int widthHistogram[5];
bzero(widthHistogram,5*sizeof(int));
const char *eight = ns.UTF8String;
size_t pos8 = 0;
size_t pos32 = 0;
int errors = 0;
for (;;) {
size_t oldpos8 = pos8;
uint32_t ch = DFNextChar(eight,&pos8);
ssize_t nbytes = pos8 - oldpos8;
assert((pos32 == len32) || (nbytes > 0));
if (pos32 < len32) {
assert(nbytes >= 1);
assert(nbytes <= 4);
widthHistogram[nbytes]++;
}
if (ch != input32[pos32])
errors++;
if (pos32 == len32)
break;
pos32++;
}
for (int i = 1; i <= 4; i++) {
printf(" Characters requiring %d bytes: %d\n",i,widthHistogram[i]);
}
printf(" Total characters: %lu\n",len32);
printf(" Total bytes: %lu\n",strlen(eight));
printf(" Errors: %d\n",errors);
return errors;
}
int testDFPrevChar(const uint32_t *input32, size_t len32)
{
printf("Testing DFPrevChar\n");
assert(len32 > 0);
NSString *ns = [[NSString alloc] initWithBytes: input32 length: len32*sizeof(uint32_t)
encoding: NSUTF32LittleEndianStringEncoding];
assert(ns != nil);
int widthHistogram[5];
bzero(widthHistogram,5*sizeof(int));
const char *eight = ns.UTF8String;
assert(strlen(eight) > 0);
size_t pos8 = strlen(eight) - 1;
size_t pos32 = len32-1;
int errors = 0;
for (;;) {
size_t oldpos8 = pos8;
uint32_t ch = DFPrevChar(eight,&pos8);
ssize_t nbytes = oldpos8 - pos8;
assert((pos32 == len32) || (nbytes > 0));
if (pos32 < len32) {
assert(nbytes >= 1);
assert(nbytes <= 4);
widthHistogram[nbytes]++;
}
if (ch != input32[pos32])
errors++;
if (pos32 == 0)
break;
pos32--;
}
for (int i = 1; i <= 4; i++) {
printf(" Characters requiring %d bytes: %d\n",i,widthHistogram[i]);
}
printf(" Total characters: %lu\n",len32);
printf(" Total bytes: %lu\n",strlen(eight));
printf(" Errors: %d\n",errors);
return errors;
}
uint32_t *genTestUTF32String(size_t len32)
{
uint32_t *str32 = (uint32_t *)malloc((len32+1)*sizeof(uint32_t));
for (size_t i = 0; i < len32; i++) {
do {
uint32_t min = 0;
uint32_t max = 0;
int nbytes = 1 + (rand()%4);
switch (nbytes) {
case 1:
min = 0;
max = 0x7F;
break;
case 2:
min = 0x80;
max = 0x7FF;
break;
case 3:
min = 0x800;
max = 0xFFFF;
break;
case 4:
min = 0x10000;
max = 0x10FFFF;
break;
default:
assert(0);
break;
}
assert(max > 0);
str32[i] = min + rand()%(max - min);
assert(str32[i] < 0x10FFFF);
} while ((str32[i] == 0) || ((str32[i] >= 0xD800) && (str32[i] <= 0xDFFF)));
}
str32[len32] = 0;
return str32;
}
int testUnicode(void)
{
int pass = 1;
uint32_t value;
uint32_t array[2];
for (value = 1; value <= 0x10FFFF; value++) {
if ((value >= 0xD800) && (value <= 0xDFFF))
continue;
@autoreleasepool {
array[0] = value;
array[1] = 0;
NSString *str = [[NSString alloc] initWithBytes: &value length: 4 encoding: NSUTF32LittleEndianStringEncoding];
const char *nsutf8 = str.UTF8String;
char *myutf8 = DFUTF32to8(array);
if (strcmp(nsutf8,myutf8)) {
printf("value = 0x%X FAIL 32 to 8\n",value);
pass = 0;
}
else {
uint32_t *myutf32 = DFUTF8To32(myutf8);
int mylen = 0;
while (myutf32[mylen] != 0)
mylen++;
if ((mylen != 1) || (myutf32[0] != value)) {
printf("value = 0x%X FAIL 8 to 32\n",value);
pass = 0;
}
else {
printf("value = 0x%X PASS\n",value);
}
}
}
}
return pass;
}
int testStrings(void)
{
size_t len32 = 1024*1024;
uint32_t *str32 = genTestUTF32String(len32);
testDFNextChar(str32,len32);
testDFPrevChar(str32,len32);
return 1;
}