// File: /workspace/github_c_makefile_star2_O1/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 $0x158, %rsp            # imm = 0x158
movq %r8, 0x30(%rsp)
movq %rcx, 0x10(%rsp)
movl %edx, 0x4(%rsp)
movq %rsi, %r14
movq %rdi, 0x20(%rsp)
movzbl 0x8(%r14), %esi
movzbl 0xa(%r14), %ebx
shll $0x8, %ebx
movzbl 0xb(%r14), %r12d
leal (%rbx,%r12), %eax
addq $0xe, %r14
testl %esi, %esi
jne 0x25fa
testw %ax, %ax
je 0x25c4
movzwl %r12w, %ebp
addl %ebx, %ebp
movq $0x0, 0x8(%rsp)
movzwl (%r14), %eax
rolw $0x8, %ax
movzwl %ax, %ebx
movl 0x2(%r14), %r15d
bswapl %r15d
movl 0x2(%r14,%rbx), %r12d
bswapl %r12d
leaq 0x6(%r14), %rsi
leaq 0x50(%rsp), %r13
movq %r13, %rdi
callq 0x2eec
cmpl 0x4(%rsp), %r15d
jne 0x256f
movq 0x10(%rsp), %rsi
testq %rsi, %rsi
sete %r15b
movq %r13, %rdi
callq 0x1050
testl %eax, %eax
sete %cl
orb %r15b, %cl
movl %r12d, %r15d
jne 0x253a
movb $0x1, %cl
movq 0x8(%rsp), %r15
testl %eax, %eax
jle 0x2569
imull 0x3ba2(%rip), %r15d     # 0x60e4
movq 0x20(%rsp), %rdi
addq %rdi, %r15
movq %r15, %rsi
movl 0x4(%rsp), %edx
movq 0x10(%rsp), %rcx
movq 0x30(%rsp), %r8
callq 0x247b
movl %eax, 0x28(%rsp)
xorl %ecx, %ecx
movq %r15, %r14
testb %cl, %cl
je 0x25a0
jmp 0x25a4
jbe 0x25a4
movl 0x3b6c(%rip), %r14d     # 0x60e4
imull 0x8(%rsp), %r14d
movq 0x20(%rsp), %rdi
addq %rdi, %r14
movq %r14, %rsi
movl 0x4(%rsp), %edx
movq 0x10(%rsp), %rcx
movq 0x30(%rsp), %r8
callq 0x247b
movl %eax, 0x28(%rsp)
xorl %eax, %eax
jmp 0x25b5
addq %rbx, %r14
addq $0x6, %r14
movb $0x1, %al
movl %r12d, %ecx
movq %rcx, 0x8(%rsp)
testb %al, %al
je 0x25e4
decw %bp
jne 0x24dc
jmp 0x25cd
movq $0x0, 0x8(%rsp)
movq 0x8(%rsp), %r14
imull 0x3b0a(%rip), %r14d     # 0x60e4
addq 0x20(%rsp), %r14
jmp 0x24a2
movl 0x28(%rsp), %eax
addq $0x158, %rsp            # imm = 0x158
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
cmpl $0xff, %esi
jne 0x29ef
movzwl %ax, %r15d
leaq 0x1346(%rip), %rdi      # 0x3957
movl %r15d, %esi
xorl %eax, %eax
callq 0x1090
xorl %eax, %eax
testw %r15w, %r15w
je 0x25e8
movzwl %r12w, %eax
orl %ebx, %eax
movzwl %ax, %eax
movl %eax, 0x38(%rsp)
xorl %r15d, %r15d
movzbl (%r14), %eax
shll $0x8, %eax
movzbl 0x1(%r14), %ecx
movq %rax, 0x28(%rsp)
movq %rcx, 0x48(%rsp)
leaq (%rax,%rcx), %rbx
movl 0x2(%r14), %ebp
bswapl %ebp
leaq 0x6(%r14), %rsi
leaq 0x50(%rsp), %r12
movq %r12, %rdi
callq 0x2eec
leaq (%r14,%rbx), %r13
addq $0x2, %r13
movzwl (%r13), %eax
rolw $0x8, %ax
movzwl %ax, %ebx
leaq 0x12e9(%rip), %rdi      # 0x3968
movl %r15d, 0x8(%rsp)
movl %r15d, %esi
movl %ebx, %edx
movl %ebp, 0x20(%rsp)
movl %ebp, %ecx
movq %r12, %r8
xorl %eax, %eax
callq 0x1090
movl $0xa, %edi
callq 0x1040
leal -0x3(%rbx), %eax
cmpl $0x2, %eax
jb 0x279f
cmpl $0x2, %ebx
je 0x27d3
cmpl $0x1, %ebx
jne 0x2981
movl 0x4(%r13), %esi
movl 0x8(%r13), %r12d
bswapl %esi
bswapl %r12d
movzbl 0x38(%r13), %ebp
movl %ebp, %eax
shll $0x8, %eax
movzbl 0x39(%r13), %ebx
orl %eax, %ebx
leaq 0x12a6(%rip), %rdi      # 0x398c
movl %r12d, %edx
xorl %eax, %eax
callq 0x1090
movzwl 0x30(%r13), %eax
movzwl 0x32(%r13), %ecx
rolw $0x8, %ax
movzwl %ax, %esi
rolw $0x8, %cx
movzwl %cx, %edx
movzwl 0x34(%r13), %eax
rolw $0x8, %ax
movzwl %ax, %ecx
movzwl 0x36(%r13), %eax
rolw $0x8, %ax
movzwl %ax, %r8d
leaq 0x1281(%rip), %rdi      # 0x39a9
movl %ebx, %r9d
xorl %eax, %eax
callq 0x1090
testb $0x4, %bpl
je 0x2746
leaq 0x1290(%rip), %rdi      # 0x39cf
xorl %eax, %eax
callq 0x1090
testb $0x40, %bpl
je 0x275a
leaq 0x1289(%rip), %rdi      # 0x39dc
xorl %eax, %eax
callq 0x1090
movl $0xa, %edi
callq 0x1040
movl 0x20(%rsp), %eax
cmpl 0x4(%rsp), %eax
jne 0x2791
cmpq $0x0, 0x10(%rsp)
je 0x2999
movq 0x10(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x1050
testl %eax, %eax
je 0x2999
addq $0x58, %r13
movb $0x1, %al
movq %r13, %r14
jmp 0x29d1
movl 0x4(%r13), %esi
bswapl %esi
movzwl 0x8(%r13), %eax
rolw $0x8, %ax
movzwl %ax, %ebx
leaq 0x12b0(%rip), %rdi      # 0x3a68
movl %ebx, %edx
xorl %eax, %eax
callq 0x1090
leaq 0xa(,%rbx,2), %r14
addq %r13, %r14
movb $0x1, %al
jmp 0x29d1
movq %r13, %r15
movzbl 0x38(%r13), %ebx
movzbl 0x39(%r13), %eax
movq 0x28(%rsp), %r13
addq 0x48(%rsp), %r13
leaq (%r14,%r13), %rcx
addq $0x32, %rcx
xorl %edx, %edx
movl $0x20, %edi
movzbl (%rcx,%rdx), %esi
cmpb $0x21, %sil
cmovbl %edi, %esi
movb %sil, 0x3f(%rsp,%rdx)
incq %rdx
cmpq $0x8, %rdx
jne 0x27f9
movl %ebx, %r8d
shll $0x8, %r8d
orl %eax, %r8d
movb $0x0, 0x47(%rsp)
movzbl 0x3a(%r15), %eax
shll $0x8, %eax
movzbl 0x3b(%r15), %ecx
movswl %ax, %edx
orl %ecx, %edx
movzbl 0x3c(%r15), %eax
shll $0x8, %eax
movzbl 0x3d(%r15), %esi
movswl %ax, %ecx
orl %esi, %ecx
leaq 0x119b(%rip), %rdi      # 0x39e7
leaq 0x3f(%rsp), %rsi
xorl %eax, %eax
callq 0x1090
testb $0x4, %bl
je 0x286b
leaq 0x116b(%rip), %rdi      # 0x39cf
xorl %eax, %eax
callq 0x1090
testb $0x40, %bl
je 0x287e
leaq 0x1165(%rip), %rdi      # 0x39dc
xorl %eax, %eax
callq 0x1090
movl $0xa, %edi
callq 0x1040
movl 0x5c(%r15), %esi
movl 0x64(%r15), %edx
bswapl %esi
bswapl %edx
leaq 0x116b(%rip), %rdi      # 0x3a06
xorl %eax, %eax
callq 0x1090
leaq (%r14,%r13), %rbp
addq $0x71, %rbp
xorl %r12d, %r12d
movl -0x7(%rbp,%r12,8), %ebx
movl -0x3(%rbp,%r12,8), %edx
bswapl %ebx
bswapl %edx
leaq 0x116c(%rip), %rdi      # 0x3a2e
movl %ebx, %esi
xorl %eax, %eax
callq 0x1090
testl %ebx, %ebx
je 0x28dd
leaq 0x1(%r12), %rax
cmpq $0x7, %r12
movq %rax, %r12
jb 0x28ad
movl $0xa, %edi
callq 0x1040
movl 0xac(%r15), %esi
movl 0xb4(%r15), %edx
bswapl %esi
bswapl %edx
leaq 0x113c(%rip), %rdi      # 0x3a3c
xorl %eax, %eax
callq 0x1090
addq %r14, %r13
addq $0xc1, %r13
xorl %r12d, %r12d
movl -0x7(%r13,%r12,8), %ebx
movl -0x3(%r13,%r12,8), %edx
bswapl %ebx
bswapl %edx
leaq 0x1105(%rip), %rdi      # 0x3a2e
movl %ebx, %esi
xorl %eax, %eax
callq 0x1090
testl %ebx, %ebx
je 0x2944
leaq 0x1(%r12), %rax
cmpq $0x7, %r12
movq %rax, %r12
jb 0x2914
movl $0xa, %edi
callq 0x1040
movl 0x20(%rsp), %eax
cmpl 0x4(%rsp), %eax
jne 0x2973
cmpq $0x0, 0x10(%rsp)
je 0x29b3
movq 0x10(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x1050
testl %eax, %eax
je 0x29b3
addq $0xf8, %r15
movb $0x1, %al
movq %r15, %r14
jmp 0x29d1
leaq 0x11b0(%rip), %rdi      # 0x3b38
callq 0x1060
xorl %eax, %eax
movl $0x0, 0x1c(%rsp)
jmp 0x29d1
leaq 0x118b(%rip), %rdi      # 0x3b2b
callq 0x1060
movq 0x30(%rsp), %rax
movl %r12d, 0x8(%rax)
movq %r13, (%rax)
jmp 0x29c7
leaq 0x1166(%rip), %rdi      # 0x3b20
callq 0x1060
movq 0x30(%rsp), %rax
movq %r15, (%rax)
movl $0x1, 0x1c(%rsp)
xorl %eax, %eax
testb %al, %al
je 0x2a04
movl 0x8(%rsp), %r15d
incl %r15d
xorl %eax, %eax
cmpl 0x38(%rsp), %r15d
jne 0x2633
jmp 0x25e8
leaq 0x1087(%rip), %rdi      # 0x3a7d
xorl %eax, %eax
callq 0x1090
xorl %eax, %eax
jmp 0x25e8
movl 0x1c(%rsp), %eax
jmp 0x25e8