// File: /workspace/github_c_makefile_star2_O3/miniupnp[P]hfsplustools/src/hfscommon.c
// Function: hfs_find_in_node
static
int hfs_find_in_node(unsigned char * catalog, unsigned char * p,
                     uint32_t parent_id, const char * name,
                     struct find_infos * infos)
{
	uint8_t kind;
#if 0
	uint32_t fLink, bLink;
	int height;
#endif
	uint16_t rec, num_records;
	uint32_t previous_node_number = 0;
	/* struct BTNodeDescriptor {
	 *  UInt32    fLink;	// next node
	 *  UInt32    bLink;	// previous node
	 *  SInt8     kind;
	 *  UInt8     height;
	 *  UInt16    numRecords;
	 *  UInt16    reserved;
	 * };
	 */
#if 0
	fLink = readu32(p);
	bLink = readu32(p+4);
	height = p[9];
#endif
	kind = p[8];
	num_records = readu16(p+10);
#if 0
	printf("Node %lu next=%u previous=%u kind=%d height=%d numRecords=%hu\n",
	       (unsigned long)(p - catalog) / catalog_node_size, fLink, bLink,
	       (int)kind, (int)height, num_records);
#endif
	p += 14;
	switch(kind) {
	case 0:	/* index */
		for(rec = 0; rec < num_records; rec++) {
			/* record */
			char str[256];
			uint16_t key_length = readu16(p);
			uint32_t cur_parent_id = readu32(p + 2);
			uint32_t node_number = readu32(p + key_length + 2);
			hfs_uni_to_str(str, sizeof(str), p + 6);
			/* Catalog file keys are compared first by parentID and
			 * then by nodeName. The parentID is compared as an
			 * unsigned 32-bit integer.
			 * For case-sensitive HFSX volumes, the characters in nodeName
			 * are compared as a sequence of unsigned 16-bit integers.
			 * For case-insensitive HFSX volumes and HFS Plus volumes,
			 * the nodeName must be compared in a case-insensitive way,
			 * as described in the Case-Insensitive String Comparison
			 * Algorithm section. */
			if(parent_id == cur_parent_id) {
				int comp = strcasecmp(str, name);
				/* https://developer.apple.com/library/archive/technotes/tn/tn1150.html#StringComparisonAlgorithm */
				if((name == NULL) || (0==comp)) {
					/* this one */
					p = catalog + node_number * catalog_node_size;
					return hfs_find_in_node(catalog, p, parent_id, name, infos);
				} else if(comp > 0) {
					/* previous one ! */
					p = catalog + previous_node_number * catalog_node_size;
					return hfs_find_in_node(catalog, p, parent_id, name, infos);
				}
			} else if(cur_parent_id > parent_id) {
				/* previous one ! */
				p = catalog + previous_node_number * catalog_node_size;
				return hfs_find_in_node(catalog, p, parent_id, name, infos);
			}
			p += key_length + 2 + 4;
			previous_node_number = node_number;
		}
		p = catalog + previous_node_number * catalog_node_size;
		return hfs_find_in_node(catalog, p, parent_id, name, infos);
	case 255:	/* LEAF */
		printf("LEAF %u records\n", num_records);
		for(rec = 0; rec < num_records; rec++) {
			char str[256];
			uint16_t record_type;
			uint16_t key_length = readu16(p);
			unsigned char * q;
			uint32_t valence;
			uint32_t folder_id;
			uint32_t cur_parent_id = readu32(p + 2);
			/* For file and folder records, this is the folder containing
			 * the file or folder represented by the record. For thread
			 * records, this is the CNID of the file or folder itself. */
			uint16_t HFSflags;
			char fileTypeCreator[9];
			int i;
			uint32_t block;
			hfs_uni_to_str(str, sizeof(str), p + 6);
			q = p + 2 + key_length;
			record_type = readu16(q);
			printf("%3d record type=%u parentId=%u \"%s\"",
			       rec, record_type, cur_parent_id, str);
			putchar('\n');
			//hexdump(q + 2, 32, 0);
			switch(record_type) {
			case 1: /* folder record */
				/* flags = readu16(q + 2); */
				valence = readu32(q + 4);
				folder_id = readu32(q + 8);
				HFSflags = readu16(q+56);
				//UInt32              createDate;
				//UInt32              contentModDate;
				//UInt32              attributeModDate;
				//UInt32              accessDate;
				//UInt32              backupDate;
				//HFSPlusBSDInfo      permissions;
				//FolderInfo          userInfo;
				//ExtendedFolderInfo  finderInfo;
				//UInt32              textEncoding;
				//UInt32              reserved;
				printf("    valence=%u folder_id=%u\n", valence, folder_id);
				printf("    folderinfo : (%u,%u)-(%u,%u) %04X",
					readu16(q+48), readu16(q+50),
					readu16(q+52), readu16(q+54),
					HFSflags);
				if(HFSflags & 0x0400) printf(" Custom Icon");
				if(HFSflags & 0x4000) printf(" Invisible");
				putchar('\n');
				if(cur_parent_id == parent_id &&
				   (name == NULL || 0 == strcasecmp(name, str))) {
					printf("FOUND FOLDER\n");
					infos->folder_id = folder_id;
					infos->p = q;
					return 1;
				}
				p = q + 88;
				break;
			case 2: /* file record */
				//file_id = readu32(q + 8);
				HFSflags = readu16(q+56);
				//UInt32              createDate;
				//UInt32              contentModDate;
				//UInt32              attributeModDate;
				//UInt32              accessDate;
				//UInt32              backupDate;
				//HFSPlusBSDInfo      permissions;
				//FileInfo            userInfo; // offset 48
				//ExtendedFileInfo    finderInfo;
				//UInt32              textEncoding;
				//UInt32              reserved2;
				//HFSPlusForkData     dataFork;  80 bytes
				//HFSPlusForkData     resourceFork; 80 bytes
				for(i=0; i<8; i++) {
					if(q[48+i] > ' ')
						fileTypeCreator[i] = q[48+i];
					else
						fileTypeCreator[i] = ' ';
				}
				fileTypeCreator[8] = '\0';
				printf("    fileinfo \"%s\" (%d,%d) %04X", fileTypeCreator, reads16(q+58), reads16(q+60), HFSflags);
				if(HFSflags & 0x0400) printf(" Custom Icon");
				if(HFSflags & 0x4000) printf(" Invisible");
				putchar('\n');
				printf("    dataFork size=%u blocks=%u extents:", readu32(q+88+4), readu32(q+88+12));
				for(i = 0; i < 8; i++) {
					block = readu32(q+88+16+i*8);
					printf(" (0x%06x, %u)", block, readu32(q+88+16+i*8+4));
					if(block == 0) break;
				}
				putchar('\n');
				printf("    resourceFork size=%u blocks=%u extents:", readu32(q+168+4), readu32(q+168+12));
				for(i = 0; i < 8; i++) {
					block = readu32(q+168+16+i*8);
					printf(" (0x%06x, %u)", block, readu32(q+168+16+i*8+4));
					if(block == 0) break;
				}
				putchar('\n');
				if(cur_parent_id == parent_id &&
				   (name == NULL || 0 == strcasecmp(name, str))) {
					printf("FOUND FILE\n");
					infos->p = q;
					return 1;
				}
				p = q + 248;
				break;
			case 3:	/* folder thread record */
			case 4:	/* file thread record */
				{
					uint16_t len;
					cur_parent_id = readu32(q + 4);
					len = readu16(q + 8);
					printf("parent_id=%u len=%u\n", cur_parent_id, len);
					p = q + 10 + len * 2;
				}
				break;
			default:
				printf("unknown\n");
				return 0;
			}
		}
		break;
	default:
		printf("unrecognized kind %u\n", kind);
	}
	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x148, %rsp            # imm = 0x148
movq %r8, 0x20(%rsp)
movq %rcx, 0x18(%rsp)
movl %edx, 0x4(%rsp)
movq %rsi, %rbx
movq %rdi, 0x10(%rsp)
leaq 0x40(%rsp), %r15
movzbl 0x8(%rbx), %esi
movzbl 0xa(%rbx), %eax
shll $0x8, %eax
movzbl 0xb(%rbx), %ecx
leal (%rax,%rcx), %edx
addq $0xe, %rbx
testl %esi, %esi
jne 0x25b1
testw %dx, %dx
je 0x2538
movzwl %cx, %r14d
addl %eax, %r14d
xorl %ebp, %ebp
movzwl (%rbx), %eax
rolw $0x8, %ax
movzwl %ax, %eax
movl 0x2(%rbx), %r12d
bswapl %r12d
movq %rax, 0x8(%rsp)
movl 0x2(%rbx,%rax), %r13d
bswapl %r13d
leaq 0x6(%rbx), %rsi
movq %r15, %rdi
callq 0x2e7f
cmpl 0x4(%rsp), %r12d
jne 0x251f
movq %rbp, 0x28(%rsp)
movq %rbx, %rbp
movq %r15, %rbx
movq %r15, %rdi
movq 0x18(%rsp), %r12
movq %r12, %rsi
callq 0x1050
testq %r12, %r12
je 0x2564
testl %eax, %eax
je 0x2564
movq %rbx, %r15
movq %rbp, %rbx
movq 0x28(%rsp), %rsi
jle 0x2521
jmp 0x2579
ja 0x2550
movq 0x8(%rsp), %rax
addq %rax, %rbx
addq $0x6, %rbx
movl %r13d, %ebp
decw %r14w
jne 0x24bb
jmp 0x253b
xorl %r13d, %r13d
imull 0x3ba1(%rip), %r13d     # 0x60e4
addq 0x10(%rsp), %r13
movq %r13, %rbx
jmp 0x248b
imull 0x3b8d(%rip), %ebp      # 0x60e4
movq 0x10(%rsp), %rdi
addq %rdi, %rbp
movq %rbp, %rsi
jmp 0x2588
imull 0x3b78(%rip), %r13d     # 0x60e4
movq 0x10(%rsp), %rdi
addq %rdi, %r13
movq %r13, %rsi
jmp 0x2588
imull 0x3b64(%rip), %esi      # 0x60e4
movq 0x10(%rsp), %rdi
addq %rdi, %rsi
movl 0x4(%rsp), %edx
movq 0x18(%rsp), %rcx
movq 0x20(%rsp), %r8
callq 0x245f
movl %eax, %ebx
movl %ebx, %eax
addq $0x148, %rsp            # imm = 0x148
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
cmpl $0xff, %esi
jne 0x2955
movq %rbx, 0x8(%rsp)
movzwl %dx, %ebp
leaq 0x138b(%rip), %rdi      # 0x3957
xorl %ebx, %ebx
movl %ebp, %esi
xorl %eax, %eax
callq 0x1090
movl %ebp, 0x30(%rsp)
testw %bp, %bp
je 0x259d
xorl %r12d, %r12d
movq 0x8(%rsp), %r14
movzbl (%r14), %eax
shll $0x8, %eax
movzbl 0x1(%r14), %ecx
movq %rax, 0x10(%rsp)
movq %rcx, %r15
leaq (%rax,%rcx), %rbx
movl 0x2(%r14), %r13d
bswapl %r13d
leaq 0x6(%r14), %rsi
leaq 0x40(%rsp), %rbp
movq %rbp, %rdi
callq 0x2e7f
addq %rbx, %r14
addq $0x2, %r14
movzwl (%r14), %eax
rolw $0x8, %ax
movzwl %ax, %ebx
leaq 0x1337(%rip), %rdi      # 0x3968
movl %r12d, 0x28(%rsp)
movl %r12d, %esi
movl %r13d, %r12d
movl %ebx, %edx
movl %r13d, %ecx
movq %rbp, %r8
xorl %eax, %eax
callq 0x1090
movl $0xa, %edi
callq 0x1040
leal -0x3(%rbx), %eax
cmpl $0x2, %eax
jb 0x274b
cmpl $0x2, %ebx
je 0x277f
cmpl $0x1, %ebx
jne 0x296a
movl 0x4(%r14), %esi
movl 0x8(%r14), %ebp
bswapl %esi
bswapl %ebp
movzbl 0x38(%r14), %ebx
movl %ebx, %eax
shll $0x8, %eax
movzbl 0x39(%r14), %r15d
orl %eax, %r15d
leaq 0x12f4(%rip), %rdi      # 0x398c
movl %ebp, %edx
xorl %eax, %eax
callq 0x1090
movzwl 0x30(%r14), %eax
movzwl 0x32(%r14), %ecx
rolw $0x8, %ax
movzwl %ax, %esi
rolw $0x8, %cx
movzwl %cx, %edx
movzwl 0x34(%r14), %eax
rolw $0x8, %ax
movzwl %ax, %ecx
movzwl 0x36(%r14), %eax
rolw $0x8, %ax
movzwl %ax, %r8d
leaq 0x12d0(%rip), %rdi      # 0x39a9
movl %r15d, %r9d
xorl %eax, %eax
callq 0x1090
testb $0x4, %bl
je 0x26f6
leaq 0x12e0(%rip), %rdi      # 0x39cf
xorl %eax, %eax
callq 0x1090
testb $0x40, %bl
je 0x2709
leaq 0x12da(%rip), %rdi      # 0x39dc
xorl %eax, %eax
callq 0x1090
movl $0xa, %edi
callq 0x1040
cmpl 0x4(%rsp), %r12d
jne 0x273d
cmpq $0x0, 0x18(%rsp)
je 0x2993
movq 0x18(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x1050
testl %eax, %eax
je 0x2993
addq $0x58, %r14
movq %r14, 0x8(%rsp)
jmp 0x293b
movl 0x4(%r14), %esi
bswapl %esi
movzwl 0x8(%r14), %eax
rolw $0x8, %ax
movzwl %ax, %ebx
leaq 0x1304(%rip), %rdi      # 0x3a68
movl %ebx, %edx
xorl %eax, %eax
callq 0x1090
leaq (%r14,%rbx,2), %rax
addq $0xa, %rax
movq %rax, 0x8(%rsp)
jmp 0x293b
movq %r14, %r13
movzbl 0x38(%r14), %ebx
movzbl 0x39(%r14), %eax
movq 0x10(%rsp), %r14
addq %r15, %r14
movq 0x8(%rsp), %rcx
addq %r14, %rcx
addq $0x32, %rcx
xorl %edx, %edx
movl $0x20, %edi
movzbl (%rcx,%rdx), %esi
cmpb $0x21, %sil
cmovbl %edi, %esi
movb %sil, 0x37(%rsp,%rdx)
incq %rdx
cmpq $0x8, %rdx
jne 0x27a7
movl %ebx, %r8d
shll $0x8, %r8d
orl %eax, %r8d
movb $0x0, 0x3f(%rsp)
movzbl 0x3a(%r13), %eax
shll $0x8, %eax
movzbl 0x3b(%r13), %ecx
movswl %ax, %edx
orl %ecx, %edx
movzbl 0x3c(%r13), %eax
shll $0x8, %eax
movzbl 0x3d(%r13), %esi
movswl %ax, %ecx
orl %esi, %ecx
leaq 0x11ed(%rip), %rdi      # 0x39e7
leaq 0x37(%rsp), %rsi
xorl %eax, %eax
callq 0x1090
testb $0x4, %bl
je 0x2819
leaq 0x11bd(%rip), %rdi      # 0x39cf
xorl %eax, %eax
callq 0x1090
testb $0x40, %bl
je 0x282c
leaq 0x11b7(%rip), %rdi      # 0x39dc
xorl %eax, %eax
callq 0x1090
movl $0xa, %edi
callq 0x1040
movl 0x5c(%r13), %esi
movl 0x64(%r13), %edx
bswapl %esi
bswapl %edx
leaq 0x11bd(%rip), %rdi      # 0x3a06
xorl %eax, %eax
callq 0x1090
movq %r14, 0x10(%rsp)
movq 0x8(%rsp), %rax
addq %rax, %r14
addq $0x71, %r14
xorl %ebp, %ebp
movl -0x7(%r14,%rbp,8), %ebx
movl -0x3(%r14,%rbp,8), %edx
bswapl %ebx
bswapl %edx
leaq 0x11b6(%rip), %rdi      # 0x3a2e
movl %ebx, %esi
xorl %eax, %eax
callq 0x1090
testl %ebx, %ebx
je 0x2892
leaq 0x1(%rbp), %rax
cmpq $0x7, %rbp
movq %rax, %rbp
jb 0x2863
movl $0xa, %edi
callq 0x1040
movl 0xac(%r13), %esi
movl 0xb4(%r13), %edx
bswapl %esi
bswapl %edx
leaq 0x1187(%rip), %rdi      # 0x3a3c
xorl %eax, %eax
callq 0x1090
movq 0x10(%rsp), %rax
movq 0x8(%rsp), %rcx
leaq (%rcx,%rax), %r14
addq $0xc1, %r14
xorl %r15d, %r15d
movl -0x7(%r14,%r15,8), %ebx
movl -0x3(%r14,%r15,8), %edx
bswapl %ebx
bswapl %edx
leaq 0x1145(%rip), %rdi      # 0x3a2e
movl %ebx, %esi
xorl %eax, %eax
callq 0x1090
testl %ebx, %ebx
je 0x2903
leaq 0x1(%r15), %rax
cmpq $0x7, %r15
movq %rax, %r15
jb 0x28d4
movl $0xa, %edi
callq 0x1040
cmpl 0x4(%rsp), %r12d
jne 0x292f
cmpq $0x0, 0x18(%rsp)
je 0x297d
movq 0x18(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x1050
testl %eax, %eax
je 0x297d
addq $0xf8, %r13
movq %r13, 0x8(%rsp)
movl 0x28(%rsp), %r12d
incl %r12d
xorl %ebx, %ebx
cmpl 0x30(%rsp), %r12d
jb 0x25e3
jmp 0x259d
leaq 0x1121(%rip), %rdi      # 0x3a7d
xorl %ebx, %ebx
xorl %eax, %eax
callq 0x1090
jmp 0x259d
leaq 0x11c7(%rip), %rdi      # 0x3b38
callq 0x1060
xorl %ebx, %ebx
jmp 0x259d
leaq 0x119c(%rip), %rdi      # 0x3b20
callq 0x1060
movq 0x20(%rsp), %rax
movq %r13, (%rax)
jmp 0x29aa
leaq 0x1191(%rip), %rdi      # 0x3b2b
callq 0x1060
movq 0x20(%rsp), %rax
movl %ebp, 0x8(%rax)
movq %r14, (%rax)
movl $0x1, %ebx
jmp 0x259d